@gmod/cram 1.6.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/craiIndex.d.ts +19 -12
  3. package/dist/craiIndex.js +63 -123
  4. package/dist/craiIndex.js.map +1 -1
  5. package/dist/cram-bundle.js +2 -17
  6. package/dist/cram-bundle.js.LICENSE.txt +17 -0
  7. package/dist/cramFile/codecs/_base.d.ts +26 -5
  8. package/dist/cramFile/codecs/_base.js +3 -39
  9. package/dist/cramFile/codecs/_base.js.map +1 -1
  10. package/dist/cramFile/codecs/beta.d.ts +7 -3
  11. package/dist/cramFile/codecs/beta.js +13 -31
  12. package/dist/cramFile/codecs/beta.js.map +1 -1
  13. package/dist/cramFile/codecs/byteArrayLength.d.ts +13 -7
  14. package/dist/cramFile/codecs/byteArrayLength.js +22 -41
  15. package/dist/cramFile/codecs/byteArrayLength.js.map +1 -1
  16. package/dist/cramFile/codecs/byteArrayStop.d.ts +9 -5
  17. package/dist/cramFile/codecs/byteArrayStop.js +25 -46
  18. package/dist/cramFile/codecs/byteArrayStop.js.map +1 -1
  19. package/dist/cramFile/codecs/dataSeriesTypes.d.ts +4 -0
  20. package/dist/cramFile/codecs/dataSeriesTypes.js +3 -0
  21. package/dist/cramFile/codecs/dataSeriesTypes.js.map +1 -0
  22. package/dist/cramFile/codecs/external.d.ts +10 -6
  23. package/dist/cramFile/codecs/external.js +26 -44
  24. package/dist/cramFile/codecs/external.js.map +1 -1
  25. package/dist/cramFile/codecs/gamma.d.ts +7 -3
  26. package/dist/cramFile/codecs/gamma.js +16 -34
  27. package/dist/cramFile/codecs/gamma.js.map +1 -1
  28. package/dist/cramFile/codecs/getBits.d.ts +7 -0
  29. package/dist/cramFile/codecs/getBits.js +26 -0
  30. package/dist/cramFile/codecs/getBits.js.map +1 -0
  31. package/dist/cramFile/codecs/huffman.d.ts +17 -13
  32. package/dist/cramFile/codecs/huffman.js +76 -85
  33. package/dist/cramFile/codecs/huffman.js.map +1 -1
  34. package/dist/cramFile/codecs/index.d.ts +4 -2
  35. package/dist/cramFile/codecs/index.js +12 -13
  36. package/dist/cramFile/codecs/index.js.map +1 -1
  37. package/dist/cramFile/codecs/subexp.d.ts +7 -3
  38. package/dist/cramFile/codecs/subexp.js +19 -36
  39. package/dist/cramFile/codecs/subexp.js.map +1 -1
  40. package/dist/cramFile/constants.d.ts +35 -35
  41. package/dist/cramFile/constants.js +1 -1
  42. package/dist/cramFile/constants.js.map +1 -1
  43. package/dist/cramFile/container/compressionScheme.d.ts +57 -11
  44. package/dist/cramFile/container/compressionScheme.js +37 -32
  45. package/dist/cramFile/container/compressionScheme.js.map +1 -1
  46. package/dist/cramFile/container/index.d.ts +23 -9
  47. package/dist/cramFile/container/index.js +74 -144
  48. package/dist/cramFile/container/index.js.map +1 -1
  49. package/dist/cramFile/encoding.d.ts +78 -0
  50. package/dist/cramFile/encoding.js +3 -0
  51. package/dist/cramFile/encoding.js.map +1 -0
  52. package/dist/cramFile/file.d.ts +91 -41
  53. package/dist/cramFile/file.js +234 -368
  54. package/dist/cramFile/file.js.map +1 -1
  55. package/dist/cramFile/filehandle.d.ts +2 -0
  56. package/dist/cramFile/filehandle.js +3 -0
  57. package/dist/cramFile/filehandle.js.map +1 -0
  58. package/dist/cramFile/index.d.ts +1 -1
  59. package/dist/cramFile/index.js +1 -1
  60. package/dist/cramFile/index.js.map +1 -1
  61. package/dist/cramFile/record.d.ts +61 -17
  62. package/dist/cramFile/record.js +153 -77
  63. package/dist/cramFile/record.js.map +1 -1
  64. package/dist/cramFile/sectionParsers.d.ts +99 -8
  65. package/dist/cramFile/sectionParsers.js +70 -80
  66. package/dist/cramFile/sectionParsers.js.map +1 -1
  67. package/dist/cramFile/slice/decodeRecord.d.ts +30 -2
  68. package/dist/cramFile/slice/decodeRecord.js +148 -118
  69. package/dist/cramFile/slice/decodeRecord.js.map +1 -1
  70. package/dist/cramFile/slice/index.d.ts +21 -14
  71. package/dist/cramFile/slice/index.js +286 -381
  72. package/dist/cramFile/slice/index.js.map +1 -1
  73. package/dist/cramFile/util.d.ts +11 -5
  74. package/dist/cramFile/util.js +19 -97
  75. package/dist/cramFile/util.js.map +1 -1
  76. package/dist/errors.d.ts +5 -10
  77. package/dist/errors.js +11 -62
  78. package/dist/errors.js.map +1 -1
  79. package/dist/index.d.ts +3 -3
  80. package/dist/index.js +3 -3
  81. package/dist/index.js.map +1 -1
  82. package/dist/indexedCramFile.d.ts +37 -12
  83. package/dist/indexedCramFile.js +114 -154
  84. package/dist/indexedCramFile.js.map +1 -1
  85. package/dist/io/index.d.ts +5 -5
  86. package/dist/io/index.js +9 -9
  87. package/dist/io/index.js.map +1 -1
  88. package/dist/rans/constants.js +3 -3
  89. package/dist/rans/constants.js.map +1 -1
  90. package/dist/rans/d04.js +15 -15
  91. package/dist/rans/d04.js.map +1 -1
  92. package/dist/rans/d14.js +21 -21
  93. package/dist/rans/d14.js.map +1 -1
  94. package/dist/rans/decoding.js +27 -30
  95. package/dist/rans/decoding.js.map +1 -1
  96. package/dist/rans/frequencies.js +11 -11
  97. package/dist/rans/frequencies.js.map +1 -1
  98. package/dist/rans/index.js +46 -49
  99. package/dist/rans/index.js.map +1 -1
  100. package/dist/sam.d.ts +8 -1
  101. package/dist/sam.js +7 -7
  102. package/dist/sam.js.map +1 -1
  103. package/dist/typescript.d.ts +3 -0
  104. package/dist/typescript.js +11 -0
  105. package/dist/typescript.js.map +1 -0
  106. package/dist/unzip-pako.js +1 -1
  107. package/dist/unzip-pako.js.map +1 -1
  108. package/dist/unzip.js +1 -1
  109. package/dist/unzip.js.map +1 -1
  110. package/errors.js +11 -62
  111. package/esm/craiIndex.d.ts +19 -12
  112. package/esm/craiIndex.js +8 -24
  113. package/esm/craiIndex.js.map +1 -1
  114. package/esm/cramFile/codecs/_base.d.ts +26 -5
  115. package/esm/cramFile/codecs/_base.js +1 -35
  116. package/esm/cramFile/codecs/_base.js.map +1 -1
  117. package/esm/cramFile/codecs/beta.d.ts +7 -3
  118. package/esm/cramFile/codecs/beta.js +4 -3
  119. package/esm/cramFile/codecs/beta.js.map +1 -1
  120. package/esm/cramFile/codecs/byteArrayLength.d.ts +13 -7
  121. package/esm/cramFile/codecs/byteArrayLength.js +1 -1
  122. package/esm/cramFile/codecs/byteArrayLength.js.map +1 -1
  123. package/esm/cramFile/codecs/byteArrayStop.d.ts +9 -5
  124. package/esm/cramFile/codecs/byteArrayStop.js +7 -9
  125. package/esm/cramFile/codecs/byteArrayStop.js.map +1 -1
  126. package/esm/cramFile/codecs/dataSeriesTypes.d.ts +4 -0
  127. package/esm/cramFile/codecs/dataSeriesTypes.js +2 -0
  128. package/esm/cramFile/codecs/dataSeriesTypes.js.map +1 -0
  129. package/esm/cramFile/codecs/external.d.ts +10 -6
  130. package/esm/cramFile/codecs/external.js +4 -3
  131. package/esm/cramFile/codecs/external.js.map +1 -1
  132. package/esm/cramFile/codecs/gamma.d.ts +7 -3
  133. package/esm/cramFile/codecs/gamma.js +5 -4
  134. package/esm/cramFile/codecs/gamma.js.map +1 -1
  135. package/esm/cramFile/codecs/getBits.d.ts +7 -0
  136. package/esm/cramFile/codecs/getBits.js +21 -0
  137. package/esm/cramFile/codecs/getBits.js.map +1 -0
  138. package/esm/cramFile/codecs/huffman.d.ts +17 -13
  139. package/esm/cramFile/codecs/huffman.js +22 -9
  140. package/esm/cramFile/codecs/huffman.js.map +1 -1
  141. package/esm/cramFile/codecs/index.d.ts +4 -2
  142. package/esm/cramFile/codecs/index.js +1 -1
  143. package/esm/cramFile/codecs/index.js.map +1 -1
  144. package/esm/cramFile/codecs/subexp.d.ts +7 -3
  145. package/esm/cramFile/codecs/subexp.js +7 -5
  146. package/esm/cramFile/codecs/subexp.js.map +1 -1
  147. package/esm/cramFile/constants.d.ts +35 -35
  148. package/esm/cramFile/constants.js.map +1 -1
  149. package/esm/cramFile/container/compressionScheme.d.ts +57 -11
  150. package/esm/cramFile/container/compressionScheme.js +15 -8
  151. package/esm/cramFile/container/compressionScheme.js.map +1 -1
  152. package/esm/cramFile/container/index.d.ts +23 -9
  153. package/esm/cramFile/container/index.js +11 -9
  154. package/esm/cramFile/container/index.js.map +1 -1
  155. package/esm/cramFile/encoding.d.ts +78 -0
  156. package/esm/cramFile/encoding.js +2 -0
  157. package/esm/cramFile/encoding.js.map +1 -0
  158. package/esm/cramFile/file.d.ts +91 -41
  159. package/esm/cramFile/file.js +59 -47
  160. package/esm/cramFile/file.js.map +1 -1
  161. package/esm/cramFile/filehandle.d.ts +2 -0
  162. package/esm/cramFile/filehandle.js +2 -0
  163. package/esm/cramFile/filehandle.js.map +1 -0
  164. package/esm/cramFile/index.d.ts +1 -1
  165. package/esm/cramFile/index.js.map +1 -1
  166. package/esm/cramFile/record.d.ts +61 -17
  167. package/esm/cramFile/record.js +83 -5
  168. package/esm/cramFile/record.js.map +1 -1
  169. package/esm/cramFile/sectionParsers.d.ts +99 -8
  170. package/esm/cramFile/sectionParsers.js +7 -17
  171. package/esm/cramFile/sectionParsers.js.map +1 -1
  172. package/esm/cramFile/slice/decodeRecord.d.ts +30 -2
  173. package/esm/cramFile/slice/decodeRecord.js +102 -70
  174. package/esm/cramFile/slice/decodeRecord.js.map +1 -1
  175. package/esm/cramFile/slice/index.d.ts +21 -14
  176. package/esm/cramFile/slice/index.js +77 -38
  177. package/esm/cramFile/slice/index.js.map +1 -1
  178. package/esm/cramFile/util.d.ts +11 -5
  179. package/esm/cramFile/util.js +11 -82
  180. package/esm/cramFile/util.js.map +1 -1
  181. package/esm/errors.d.ts +5 -10
  182. package/esm/errors.js +0 -5
  183. package/esm/errors.js.map +1 -1
  184. package/esm/index.d.ts +3 -3
  185. package/esm/index.js.map +1 -1
  186. package/esm/indexedCramFile.d.ts +37 -12
  187. package/esm/indexedCramFile.js +19 -8
  188. package/esm/indexedCramFile.js.map +1 -1
  189. package/esm/io/index.d.ts +5 -5
  190. package/esm/io/index.js +3 -3
  191. package/esm/io/index.js.map +1 -1
  192. package/esm/sam.d.ts +8 -1
  193. package/esm/sam.js.map +1 -1
  194. package/esm/typescript.d.ts +3 -0
  195. package/esm/typescript.js +7 -0
  196. package/esm/typescript.js.map +1 -0
  197. package/package.json +18 -11
  198. package/src/{craiIndex.js → craiIndex.ts} +37 -31
  199. package/src/cramFile/codecs/_base.ts +45 -0
  200. package/src/cramFile/codecs/beta.ts +34 -0
  201. package/src/cramFile/codecs/{byteArrayLength.js → byteArrayLength.ts} +27 -5
  202. package/src/cramFile/codecs/{byteArrayStop.js → byteArrayStop.ts} +25 -12
  203. package/src/cramFile/codecs/dataSeriesTypes.ts +39 -0
  204. package/src/cramFile/codecs/{external.js → external.ts} +28 -12
  205. package/src/cramFile/codecs/gamma.ts +42 -0
  206. package/src/cramFile/codecs/getBits.ts +28 -0
  207. package/src/cramFile/codecs/{huffman.js → huffman.ts} +48 -15
  208. package/src/cramFile/codecs/{index.js → index.ts} +9 -3
  209. package/src/cramFile/codecs/subexp.ts +45 -0
  210. package/src/cramFile/{constants.js → constants.ts} +0 -0
  211. package/src/cramFile/container/{compressionScheme.js → compressionScheme.ts} +50 -18
  212. package/src/cramFile/container/{index.js → index.ts} +13 -13
  213. package/src/cramFile/encoding.ts +98 -0
  214. package/src/cramFile/{file.js → file.ts} +136 -62
  215. package/src/cramFile/filehandle.ts +3 -0
  216. package/src/cramFile/{index.js → index.ts} +0 -0
  217. package/src/cramFile/{record.js → record.ts} +185 -14
  218. package/src/cramFile/{sectionParsers.js → sectionParsers.ts} +148 -20
  219. package/src/cramFile/slice/{decodeRecord.js → decodeRecord.ts} +158 -105
  220. package/src/cramFile/slice/{index.js → index.ts} +138 -63
  221. package/src/cramFile/{util.js → util.ts} +28 -17
  222. package/src/{errors.js → errors.ts} +0 -5
  223. package/src/{index.js → index.ts} +0 -0
  224. package/src/{indexedCramFile.js → indexedCramFile.ts} +79 -19
  225. package/src/io/{index.js → index.ts} +10 -5
  226. package/src/{sam.js → sam.ts} +7 -2
  227. package/src/typescript.ts +17 -0
  228. package/src/typings/binary-parser.d.ts +44 -0
  229. package/src/typings/bzip2.d.ts +7 -0
  230. package/src/typings/htscodecs.d.ts +6 -0
  231. package/dist/io/bufferCache.d.ts +0 -12
  232. package/dist/io/bufferCache.js +0 -112
  233. package/dist/io/bufferCache.js.map +0 -1
  234. package/dist/io/localFile.d.ts +0 -10
  235. package/dist/io/localFile.js +0 -108
  236. package/dist/io/localFile.js.map +0 -1
  237. package/dist/io/remoteFile.d.ts +0 -16
  238. package/dist/io/remoteFile.js +0 -143
  239. package/dist/io/remoteFile.js.map +0 -1
  240. package/esm/io/bufferCache.d.ts +0 -12
  241. package/esm/io/bufferCache.js +0 -54
  242. package/esm/io/bufferCache.js.map +0 -1
  243. package/esm/io/localFile.d.ts +0 -10
  244. package/esm/io/localFile.js +0 -31
  245. package/esm/io/localFile.js.map +0 -1
  246. package/esm/io/remoteFile.d.ts +0 -16
  247. package/esm/io/remoteFile.js +0 -64
  248. package/esm/io/remoteFile.js.map +0 -1
  249. package/src/cramFile/codecs/_base.js +0 -49
  250. package/src/cramFile/codecs/beta.js +0 -23
  251. package/src/cramFile/codecs/gamma.js +0 -30
  252. package/src/cramFile/codecs/subexp.js +0 -32
  253. package/src/io/bufferCache.js +0 -66
  254. package/src/io/localFile.js +0 -35
  255. package/src/io/remoteFile.js +0 -71
@@ -0,0 +1,39 @@
1
+ import { CramEncoding } from '../encoding'
2
+
3
+ export type DataType = 'int' | 'byte' | 'long' | 'byteArray'
4
+
5
+ export type DataSeriesEncodingKey =
6
+ | 'BF'
7
+ | 'CF'
8
+ | 'RI'
9
+ | 'RL'
10
+ | 'AP'
11
+ | 'RG'
12
+ | 'RN'
13
+ | 'MF'
14
+ | 'NS'
15
+ | 'NP'
16
+ | 'TS'
17
+ | 'NF'
18
+ | 'TL'
19
+ | 'FN'
20
+ | 'FC'
21
+ | 'FP'
22
+ | 'DL'
23
+ | 'BB'
24
+ | 'QQ'
25
+ | 'BS'
26
+ | 'IN'
27
+ | 'RS'
28
+ | 'PD'
29
+ | 'HC'
30
+ | 'SC'
31
+ | 'MQ'
32
+ | 'BA'
33
+ | 'QS'
34
+ | 'TC'
35
+ | 'TN'
36
+ // | 'TM'
37
+ // | 'TV'
38
+
39
+ export type DataSeriesEncodingMap = Record<DataSeriesEncodingKey, CramEncoding>
@@ -1,13 +1,24 @@
1
- import {
2
- CramUnimplementedError,
3
- CramMalformedError,
4
- CramBufferOverrunError,
5
- } from '../../errors'
6
- import CramCodec from './_base'
1
+ import { CramMalformedError, CramUnimplementedError } from '../../errors'
2
+ import CramCodec, { Cursor, Cursors } from './_base'
7
3
  import { parseItf8 } from '../util'
4
+ import CramSlice from '../slice'
5
+ import { CramFileBlock } from '../file'
6
+ import { CramBufferOverrunError } from './getBits'
7
+ import { ExternalCramEncoding } from '../encoding'
8
8
 
9
- export default class ExternalCodec extends CramCodec {
10
- constructor(parameters = {}, dataType) {
9
+ export default class ExternalCodec extends CramCodec<
10
+ 'int' | 'byte',
11
+ ExternalCramEncoding['parameters']
12
+ > {
13
+ private readonly _decodeData: (
14
+ contentBlock: CramFileBlock,
15
+ cursor: Cursor,
16
+ ) => number
17
+
18
+ constructor(
19
+ parameters: ExternalCramEncoding['parameters'],
20
+ dataType: 'int' | 'byte',
21
+ ) {
11
22
  super(parameters, dataType)
12
23
  if (this.dataType === 'int') {
13
24
  this._decodeData = this._decodeInt
@@ -20,7 +31,12 @@ export default class ExternalCodec extends CramCodec {
20
31
  }
21
32
  }
22
33
 
23
- decode(slice, coreDataBlock, blocksByContentId, cursors) {
34
+ decode(
35
+ slice: CramSlice,
36
+ coreDataBlock: CramFileBlock,
37
+ blocksByContentId: Record<number, CramFileBlock>,
38
+ cursors: Cursors,
39
+ ) {
24
40
  const { blockContentId } = this.parameters
25
41
  const contentBlock = blocksByContentId[blockContentId]
26
42
  if (!contentBlock) {
@@ -32,16 +48,16 @@ export default class ExternalCodec extends CramCodec {
32
48
  return this._decodeData(contentBlock, cursor)
33
49
  }
34
50
 
35
- _decodeInt(contentBlock, cursor) {
51
+ _decodeInt(contentBlock: CramFileBlock, cursor: Cursor) {
36
52
  const [result, bytesRead] = parseItf8(
37
53
  contentBlock.content,
38
54
  cursor.bytePosition,
39
55
  )
40
- cursor.bytePosition += bytesRead
56
+ cursor.bytePosition = cursor.bytePosition + bytesRead
41
57
  return result
42
58
  }
43
59
 
44
- _decodeByte(contentBlock, cursor) {
60
+ _decodeByte(contentBlock: CramFileBlock, cursor: Cursor) {
45
61
  if (cursor.bytePosition >= contentBlock.content.length) {
46
62
  throw new CramBufferOverrunError(
47
63
  'attempted to read beyond end of block. this file seems truncated.',
@@ -0,0 +1,42 @@
1
+ import { CramUnimplementedError } from '../../errors'
2
+ import CramCodec, { Cursors } from './_base'
3
+ import { getBits } from './getBits'
4
+ import { GammaEncoding } from '../encoding'
5
+ import CramSlice from '../slice'
6
+ import { CramFileBlock } from '../file'
7
+
8
+ export default class GammaCodec extends CramCodec<
9
+ 'int',
10
+ GammaEncoding['parameters']
11
+ > {
12
+ constructor(parameters: GammaEncoding['parameters'], dataType: 'int') {
13
+ super(parameters, dataType)
14
+ if (this.dataType !== 'int') {
15
+ throw new CramUnimplementedError(
16
+ `${this.dataType} decoding not yet implemented by GAMMA codec`,
17
+ )
18
+ }
19
+ }
20
+
21
+ decode(
22
+ slice: CramSlice,
23
+ coreDataBlock: CramFileBlock,
24
+ blocksByContentId: Record<number, CramFileBlock>,
25
+ cursors: Cursors,
26
+ ) {
27
+ let length = 1
28
+
29
+ while (getBits(coreDataBlock.content, cursors.coreBlock, 1) === 0) {
30
+ length = length + 1
31
+ }
32
+
33
+ const readBits = getBits(
34
+ coreDataBlock.content,
35
+ cursors.coreBlock,
36
+ length - 1,
37
+ )
38
+
39
+ const value = readBits | (1 << (length - 1))
40
+ return value - this.parameters.offset
41
+ }
42
+ }
@@ -0,0 +1,28 @@
1
+ export class CramBufferOverrunError extends Error {}
2
+
3
+ export function getBits(
4
+ data: Buffer,
5
+ cursor: { bytePosition: number; bitPosition: number },
6
+ numBits: number,
7
+ ) {
8
+ let val = 0
9
+ if (
10
+ cursor.bytePosition + (7 - cursor.bitPosition + numBits) / 8 >
11
+ data.length
12
+ ) {
13
+ throw new CramBufferOverrunError(
14
+ 'read error during decoding. the file seems to be truncated.',
15
+ )
16
+ }
17
+ for (let dlen = numBits; dlen; dlen--) {
18
+ // get the next `dlen` bits in the input, put them in val
19
+ val <<= 1
20
+ val |= (data[cursor.bytePosition] >> cursor.bitPosition) & 1
21
+ cursor.bitPosition -= 1
22
+ if (cursor.bitPosition < 0) {
23
+ cursor.bytePosition += 1
24
+ }
25
+ cursor.bitPosition &= 7
26
+ }
27
+ return val
28
+ }
@@ -1,14 +1,36 @@
1
1
  import { CramMalformedError } from '../../errors'
2
- import CramCodec from './_base'
2
+ import CramCodec, { Cursor, Cursors } from './_base'
3
+ import { getBits } from './getBits'
4
+ import { HuffmanEncoding } from '../encoding'
3
5
 
4
- function numberOfSetBits(ii) {
6
+ import CramSlice from '../slice'
7
+ import { CramFileBlock } from '../file'
8
+
9
+ function numberOfSetBits(ii: number) {
5
10
  let i = (ii - (ii >> 1)) & 0x55555555
6
11
  i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
7
12
  return (((i + (i >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24
8
13
  }
9
14
 
10
- export default class HuffmanIntCodec extends CramCodec {
11
- constructor(parameters = {}, dataType) {
15
+ type Code = { bitLength: number; value: number; bitCode: number }
16
+
17
+ export default class HuffmanIntCodec extends CramCodec<
18
+ 'byte' | 'int',
19
+ HuffmanEncoding['parameters']
20
+ > {
21
+ private codes: Record<number, Code> = {}
22
+ private codeBook: Record<number, number[]> = {}
23
+ private sortedByValue: Code[] = []
24
+ private sortedCodes: Code[] = []
25
+ private sortedValuesByBitCode: number[] = []
26
+ private sortedBitCodes: number[] = []
27
+ private sortedBitLengthsByBitCode: number[] = []
28
+ private bitCodeToValue: number[] = []
29
+
30
+ constructor(
31
+ parameters: HuffmanEncoding['parameters'],
32
+ dataType: 'byte' | 'int',
33
+ ) {
12
34
  super(parameters, dataType)
13
35
  if (!['byte', 'int'].includes(this.dataType)) {
14
36
  throw new TypeError(
@@ -28,7 +50,9 @@ export default class HuffmanIntCodec extends CramCodec {
28
50
 
29
51
  buildCodeBook() {
30
52
  // parse the parameters together into a `codes` data structure
31
- let codes = new Array(this.parameters.numCodes)
53
+ let codes: Array<{ symbol: number; bitLength: number }> = new Array(
54
+ this.parameters.numCodes,
55
+ )
32
56
  for (let i = 0; i < this.parameters.numCodes; i += 1) {
33
57
  codes[i] = {
34
58
  symbol: this.parameters.symbols[i],
@@ -54,16 +78,20 @@ export default class HuffmanIntCodec extends CramCodec {
54
78
  let codeLength = 0
55
79
  let codeValue = -1
56
80
  Object.entries(this.codeBook).forEach(([bitLength, symbols]) => {
57
- bitLength = parseInt(bitLength, 10)
81
+ const bitLengthInt = parseInt(bitLength, 10)
58
82
  symbols.forEach(symbol => {
59
- const code = { bitLength, value: symbol }
60
- codeValue += 1
61
- const delta = bitLength - codeLength // new length?
62
- codeValue <<= delta // pad with 0's
83
+ const code = {
84
+ bitLength: bitLengthInt,
85
+ value: symbol,
86
+ bitCode: 0,
87
+ }
88
+ codeValue = codeValue + 1
89
+ const delta = bitLengthInt - codeLength // new length?
90
+ codeValue = codeValue << delta // pad with 0's
63
91
  code.bitCode = codeValue // calculated: huffman code
64
- codeLength += delta // adjust current code length
92
+ codeLength = codeLength + delta // adjust current code length
65
93
 
66
- if (numberOfSetBits(codeValue) > bitLength) {
94
+ if (numberOfSetBits(codeValue) > bitLengthInt) {
67
95
  throw new CramMalformedError('Symbol out of range')
68
96
  }
69
97
 
@@ -93,7 +121,12 @@ export default class HuffmanIntCodec extends CramCodec {
93
121
  }
94
122
  }
95
123
 
96
- decode(slice, coreDataBlock, blocksByContentId, cursors) {
124
+ decode(
125
+ slice: CramSlice,
126
+ coreDataBlock: CramFileBlock,
127
+ blocksByContentId: Record<number, CramFileBlock>,
128
+ cursors: Cursors,
129
+ ) {
97
130
  return this._decode(slice, coreDataBlock, cursors.coreBlock)
98
131
  }
99
132
 
@@ -106,7 +139,7 @@ export default class HuffmanIntCodec extends CramCodec {
106
139
  return this.sortedCodes[0].value
107
140
  }
108
141
 
109
- _decode(slice, coreDataBlock, coreCursor) {
142
+ _decode(slice: CramSlice, coreDataBlock: CramFileBlock, coreCursor: Cursor) {
110
143
  const input = coreDataBlock.content
111
144
 
112
145
  let prevLen = 0
@@ -114,7 +147,7 @@ export default class HuffmanIntCodec extends CramCodec {
114
147
  for (let i = 0; i < this.sortedCodes.length; i += 1) {
115
148
  const length = this.sortedCodes[i].bitLength
116
149
  bits <<= length - prevLen
117
- bits |= this._getBits(input, coreCursor, length - prevLen)
150
+ bits |= getBits(input, coreCursor, length - prevLen)
118
151
  prevLen = length
119
152
  {
120
153
  const index = this.bitCodeToValue[bits]
@@ -7,6 +7,9 @@ import ByteArrayLengthCodec from './byteArrayLength'
7
7
  import BetaCodec from './beta'
8
8
  import GammaCodec from './gamma'
9
9
  import SubexpCodec from './subexp'
10
+ import CramCodec from './_base'
11
+ import { CramEncoding } from '../encoding'
12
+ import { DataType } from './dataSeriesTypes'
10
13
 
11
14
  const codecClasses = {
12
15
  1: ExternalCodec,
@@ -20,11 +23,14 @@ const codecClasses = {
20
23
  9: GammaCodec,
21
24
  }
22
25
 
23
- export function getCodecClassWithId(id) {
24
- return codecClasses[id]
26
+ function getCodecClassWithId(id: number) {
27
+ return (codecClasses as any)[id]
25
28
  }
26
29
 
27
- export function instantiateCodec(encodingData, dataType) {
30
+ export function instantiateCodec<TResult extends DataType = DataType>(
31
+ encodingData: CramEncoding,
32
+ dataType: DataType | 'ignore',
33
+ ): CramCodec<TResult> {
28
34
  const CodecClass = getCodecClassWithId(
29
35
  dataType === 'ignore' ? 0 : encodingData.codecId,
30
36
  )
@@ -0,0 +1,45 @@
1
+ import { CramUnimplementedError } from '../../errors'
2
+ import CramCodec, { Cursors } from './_base'
3
+ import { getBits } from './getBits'
4
+ import CramSlice from '../slice'
5
+ import { CramFileBlock } from '../file'
6
+ import { SubexpEncoding } from '../encoding'
7
+
8
+ export default class SubexpCodec extends CramCodec<
9
+ 'int',
10
+ SubexpEncoding['parameters']
11
+ > {
12
+ constructor(parameters: SubexpEncoding['parameters'], dataType: 'int') {
13
+ super(parameters, dataType)
14
+ if (this.dataType !== 'int') {
15
+ throw new CramUnimplementedError(
16
+ `${this.dataType} decoding not yet implemented by SUBEXP codec`,
17
+ )
18
+ }
19
+ }
20
+
21
+ decode(
22
+ slice: CramSlice,
23
+ coreDataBlock: CramFileBlock,
24
+ blocksByContentId: Record<number, CramFileBlock>,
25
+ cursors: Cursors,
26
+ ) {
27
+ let numLeadingOnes = 0
28
+ while (getBits(coreDataBlock.content, cursors.coreBlock, 1)) {
29
+ numLeadingOnes = numLeadingOnes + 1
30
+ }
31
+
32
+ let b
33
+ let n
34
+ if (numLeadingOnes === 0) {
35
+ b = this.parameters.K
36
+ n = getBits(coreDataBlock.content, cursors.coreBlock, b)
37
+ } else {
38
+ b = numLeadingOnes + this.parameters.K - 1
39
+ const bits = getBits(coreDataBlock.content, cursors.coreBlock, b)
40
+ n = (1 << b) | bits
41
+ }
42
+
43
+ return n - this.parameters.offset
44
+ }
45
+ }
File without changes
@@ -1,5 +1,12 @@
1
- import { CramMalformedError } from '../../errors'
2
1
  import { instantiateCodec } from '../codecs'
2
+ import CramCodec from '../codecs/_base'
3
+ import { CramCompressionHeader, CramPreservationMap } from '../sectionParsers'
4
+ import { CramEncoding } from '../encoding'
5
+ import { CramMalformedError } from '../../errors'
6
+ import {
7
+ DataSeriesEncodingKey,
8
+ DataSeriesEncodingMap,
9
+ } from '../codecs/dataSeriesTypes'
3
10
 
4
11
  // the hardcoded data type to be decoded for each core
5
12
  // data field
@@ -34,12 +41,14 @@ const dataSeriesTypes = {
34
41
  QS: 'byte',
35
42
  QQ: 'byteArray',
36
43
  TL: 'int',
37
- TM: 'ignore',
38
- TV: 'ignore',
39
- }
44
+ // TM: 'ignore',
45
+ // TV: 'ignore',
46
+ } as const
47
+
48
+ export type DataSeriesTypes = typeof dataSeriesTypes
40
49
 
41
- function parseSubstitutionMatrix(byteArray) {
42
- const matrix = new Array(5)
50
+ function parseSubstitutionMatrix(byteArray: number[]) {
51
+ const matrix: string[][] = new Array(5)
43
52
  for (let i = 0; i < 5; i += 1) {
44
53
  matrix[i] = new Array(4)
45
54
  }
@@ -72,25 +81,44 @@ function parseSubstitutionMatrix(byteArray) {
72
81
  return matrix
73
82
  }
74
83
 
84
+ type DataSeriesCache = {
85
+ [K in DataSeriesEncodingKey]?: CramCodec<DataSeriesTypes[K]>
86
+ }
87
+
75
88
  export default class CramContainerCompressionScheme {
76
- constructor(content) {
77
- Object.assign(this, content)
89
+ public readNamesIncluded: boolean
90
+ public APdelta: boolean
91
+ public referenceRequired: boolean
92
+ public tagIdsDictionary: Record<number, string[]>
93
+ public substitutionMatrix: string[][]
94
+ public dataSeriesCodecCache: DataSeriesCache = {}
95
+ public tagCodecCache: Record<string, CramCodec> = {}
96
+ public tagEncoding: Record<string, CramEncoding> = {}
97
+ public dataSeriesEncoding: DataSeriesEncodingMap
98
+ private preservation: CramPreservationMap
99
+ private _endPosition: number
100
+ private _size: number
101
+
102
+ constructor(content: CramCompressionHeader) {
103
+ // Object.assign(this, content)
78
104
  // interpret some of the preservation map tags for convenient use
79
105
  this.readNamesIncluded = content.preservation.RN
80
106
  this.APdelta = content.preservation.AP
81
107
  this.referenceRequired = !!content.preservation.RR
82
108
  this.tagIdsDictionary = content.preservation.TD
83
109
  this.substitutionMatrix = parseSubstitutionMatrix(content.preservation.SM)
84
-
85
- this.dataSeriesCodecCache = new Map()
86
- this.tagCodecCache = {}
110
+ this.dataSeriesEncoding = content.dataSeriesEncoding
111
+ this.tagEncoding = content.tagEncoding
112
+ this.preservation = content.preservation
113
+ this._size = content._size
114
+ this._endPosition = content._endPosition
87
115
  }
88
116
 
89
117
  /**
90
118
  * @param {string} tagName three-character tag name
91
119
  * @private
92
120
  */
93
- getCodecForTag(tagName) {
121
+ getCodecForTag(tagName: string): CramCodec {
94
122
  if (!this.tagCodecCache[tagName]) {
95
123
  const encodingData = this.tagEncoding[tagName]
96
124
  if (encodingData) {
@@ -108,12 +136,15 @@ export default class CramContainerCompressionScheme {
108
136
  * @param {number} tagListId ID of the tag list to fetch from the tag dictionary
109
137
  * @private
110
138
  */
111
- getTagNames(tagListId) {
139
+ getTagNames(tagListId: number) {
112
140
  return this.tagIdsDictionary[tagListId]
113
141
  }
114
142
 
115
- getCodecForDataSeries(dataSeriesName) {
116
- let r = this.dataSeriesCodecCache.get(dataSeriesName)
143
+ getCodecForDataSeries<TDataSeries extends DataSeriesEncodingKey>(
144
+ dataSeriesName: TDataSeries,
145
+ ): CramCodec<DataSeriesTypes[TDataSeries]> | undefined {
146
+ let r: CramCodec<DataSeriesTypes[TDataSeries]> | undefined =
147
+ this.dataSeriesCodecCache[dataSeriesName]
117
148
  if (r === undefined) {
118
149
  const encodingData = this.dataSeriesEncoding[dataSeriesName]
119
150
  if (encodingData) {
@@ -124,19 +155,20 @@ export default class CramContainerCompressionScheme {
124
155
  )
125
156
  }
126
157
  r = instantiateCodec(encodingData, dataType)
127
- this.dataSeriesCodecCache.set(dataSeriesName, r)
158
+ // didn't find a way to make TS understand this
159
+ this.dataSeriesCodecCache[dataSeriesName] = r as CramCodec<any>
128
160
  }
129
161
  }
130
162
  return r
131
163
  }
132
164
 
133
165
  toJSON() {
134
- const data = {}
166
+ const data: any = {}
135
167
  Object.keys(this).forEach(k => {
136
168
  if (/Cache$/.test(k)) {
137
169
  return
138
170
  }
139
- data[k] = this[k]
171
+ data[k] = (this as any)[k]
140
172
  })
141
173
  return data
142
174
  }
@@ -3,15 +3,10 @@ import { CramMalformedError } from '../../errors'
3
3
  import { itf8Size, parseItem, tinyMemoize } from '../util'
4
4
  import CramSlice from '../slice'
5
5
  import CramContainerCompressionScheme from './compressionScheme'
6
+ import CramFile from '../file'
6
7
 
7
8
  export default class CramContainer {
8
- constructor(cramFile, position) {
9
- // cram file this container comes from
10
- this.file = cramFile
11
- // position of this container in the file
12
- this.filePosition = position
13
- // console.log(`container: ${this.filePosition}`)
14
- }
9
+ constructor(public file: CramFile, public filePosition: number) {}
15
10
 
16
11
  // memoize
17
12
  getHeader() {
@@ -28,6 +23,9 @@ export default class CramContainer {
28
23
  }
29
24
  const sectionParsers = await this.file.getSectionParsers()
30
25
  const block = await this.getFirstBlock()
26
+ if (block === undefined) {
27
+ return undefined
28
+ }
31
29
  if (block.contentType !== 'COMPRESSION_HEADER') {
32
30
  throw new CramMalformedError(
33
31
  `invalid content type ${block.contentType} in what is supposed to be the compression header block`,
@@ -39,8 +37,10 @@ export default class CramContainer {
39
37
  0,
40
38
  block.contentPosition,
41
39
  )
42
- block.content = content
43
- return block
40
+ return {
41
+ ...block,
42
+ parsedContent: content,
43
+ }
44
44
  }
45
45
 
46
46
  async getFirstBlock() {
@@ -55,16 +55,16 @@ export default class CramContainer {
55
55
  if (!header) {
56
56
  return undefined
57
57
  }
58
- return new CramContainerCompressionScheme(header.content)
58
+ return new CramContainerCompressionScheme(header.parsedContent)
59
59
  }
60
60
 
61
- getSlice(slicePosition, sliceSize) {
61
+ getSlice(slicePosition: number, sliceSize: number) {
62
62
  // note: slicePosition is relative to the end of the container header
63
63
  // TODO: perhaps we should cache slices?
64
64
  return new CramSlice(this, slicePosition, sliceSize)
65
65
  }
66
66
 
67
- async _readContainerHeader(position) {
67
+ async _readContainerHeader(position: number) {
68
68
  const sectionParsers = await this.file.getSectionParsers()
69
69
  const { cramContainerHeader1, cramContainerHeader2 } = sectionParsers
70
70
  const { size: fileSize } = await this.file.stat()
@@ -77,7 +77,7 @@ export default class CramContainer {
77
77
  // how much to buffer until you read numLandmarks
78
78
  const bytes1 = Buffer.allocUnsafe(cramContainerHeader1.maxLength)
79
79
  await this.file.read(bytes1, 0, cramContainerHeader1.maxLength, position)
80
- const header1 = parseItem(bytes1, cramContainerHeader1.parser)
80
+ const header1 = parseItem(bytes1, cramContainerHeader1.parser) as any
81
81
  const numLandmarksSize = itf8Size(header1.numLandmarks)
82
82
  if (position + header1.length >= fileSize) {
83
83
  console.warn(
@@ -0,0 +1,98 @@
1
+ export type NullEncoding = {
2
+ codecId: 0
3
+ parametersBytes: number
4
+ parameters: Record<string, never>
5
+ }
6
+
7
+ export type ExternalCramEncoding = {
8
+ codecId: 1
9
+ parametersBytes: number
10
+ parameters: {
11
+ blockContentId: number
12
+ }
13
+ }
14
+
15
+ export type GolombEncoding = {
16
+ codecId: 2
17
+ parametersBytes: number
18
+ parameters: {
19
+ offset: number
20
+ M: number
21
+ }
22
+ }
23
+
24
+ export type HuffmanEncoding = {
25
+ codecId: 3
26
+ parametersBytes: number
27
+ parameters: {
28
+ numCodes: number
29
+ symbols: number[]
30
+ numLengths: number
31
+ bitLengths: number[]
32
+ }
33
+ }
34
+
35
+ export type ByteArrayLengthEncoding = {
36
+ codecId: 4
37
+ parametersBytes: number
38
+ parameters: {
39
+ lengthsEncoding: CramEncoding
40
+ valuesEncoding: CramEncoding
41
+ }
42
+ }
43
+
44
+ export type ByteArrayStopCramEncoding = {
45
+ codecId: 5
46
+ parametersBytes: number
47
+ parameters: {
48
+ stopByte: number
49
+ blockContentId: number
50
+ }
51
+ }
52
+
53
+ export type BetaEncoding = {
54
+ codecId: 6
55
+ parametersBytes: number
56
+ parameters: {
57
+ offset: number
58
+ length: number // int number of bits
59
+ }
60
+ }
61
+
62
+ export type SubexpEncoding = {
63
+ codecId: 7
64
+ parametersBytes: number
65
+ parameters: {
66
+ offset: number
67
+ K: number
68
+ }
69
+ }
70
+
71
+ export type GolombRiceEncoding = {
72
+ codecId: 8
73
+ parametersBytes: number
74
+ parameters: {
75
+ offset: number
76
+ log2m: number
77
+ }
78
+ }
79
+
80
+ export type GammaEncoding = {
81
+ codecId: 9
82
+ parametersBytes: number
83
+ parameters: {
84
+ offset: number
85
+ }
86
+ }
87
+
88
+ export type CramEncoding =
89
+ | NullEncoding
90
+ | ExternalCramEncoding
91
+ | GolombEncoding
92
+ | HuffmanEncoding
93
+ | ByteArrayLengthEncoding
94
+ | ByteArrayStopCramEncoding
95
+ | BetaEncoding
96
+ | SubexpEncoding
97
+ | GolombRiceEncoding
98
+ | GammaEncoding