@gmod/cram 2.0.4 → 3.0.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 (64) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cram-bundle.js +1 -1
  3. package/dist/cramFile/codecs/byteArrayLength.js +1 -1
  4. package/dist/cramFile/codecs/byteArrayLength.js.map +1 -1
  5. package/dist/cramFile/codecs/external.js +1 -1
  6. package/dist/cramFile/codecs/external.js.map +1 -1
  7. package/dist/cramFile/codecs/huffman.js +2 -1
  8. package/dist/cramFile/codecs/huffman.js.map +1 -1
  9. package/dist/cramFile/container/compressionScheme.d.ts +0 -3
  10. package/dist/cramFile/container/compressionScheme.js +0 -4
  11. package/dist/cramFile/container/compressionScheme.js.map +1 -1
  12. package/dist/cramFile/container/index.d.ts +56 -3
  13. package/dist/cramFile/container/index.js +15 -9
  14. package/dist/cramFile/container/index.js.map +1 -1
  15. package/dist/cramFile/file.d.ts +24 -59
  16. package/dist/cramFile/file.js +21 -26
  17. package/dist/cramFile/file.js.map +1 -1
  18. package/dist/cramFile/record.d.ts +1 -1
  19. package/dist/cramFile/sectionParsers.d.ts +195 -48
  20. package/dist/cramFile/sectionParsers.js +621 -303
  21. package/dist/cramFile/sectionParsers.js.map +1 -1
  22. package/dist/cramFile/slice/index.d.ts +23 -1
  23. package/dist/cramFile/slice/index.js +9 -6
  24. package/dist/cramFile/slice/index.js.map +1 -1
  25. package/dist/cramFile/util.d.ts +6 -4
  26. package/dist/cramFile/util.js +88 -6
  27. package/dist/cramFile/util.js.map +1 -1
  28. package/esm/cramFile/codecs/byteArrayLength.js +1 -1
  29. package/esm/cramFile/codecs/byteArrayLength.js.map +1 -1
  30. package/esm/cramFile/codecs/external.js +1 -1
  31. package/esm/cramFile/codecs/external.js.map +1 -1
  32. package/esm/cramFile/codecs/huffman.js +2 -1
  33. package/esm/cramFile/codecs/huffman.js.map +1 -1
  34. package/esm/cramFile/container/compressionScheme.d.ts +0 -3
  35. package/esm/cramFile/container/compressionScheme.js +0 -4
  36. package/esm/cramFile/container/compressionScheme.js.map +1 -1
  37. package/esm/cramFile/container/index.d.ts +56 -3
  38. package/esm/cramFile/container/index.js +15 -9
  39. package/esm/cramFile/container/index.js.map +1 -1
  40. package/esm/cramFile/file.d.ts +24 -59
  41. package/esm/cramFile/file.js +22 -25
  42. package/esm/cramFile/file.js.map +1 -1
  43. package/esm/cramFile/record.d.ts +1 -1
  44. package/esm/cramFile/sectionParsers.d.ts +195 -48
  45. package/esm/cramFile/sectionParsers.js +620 -303
  46. package/esm/cramFile/sectionParsers.js.map +1 -1
  47. package/esm/cramFile/slice/index.d.ts +23 -1
  48. package/esm/cramFile/slice/index.js +10 -7
  49. package/esm/cramFile/slice/index.js.map +1 -1
  50. package/esm/cramFile/util.d.ts +6 -4
  51. package/esm/cramFile/util.js +87 -6
  52. package/esm/cramFile/util.js.map +1 -1
  53. package/package.json +7 -8
  54. package/src/cramFile/codecs/byteArrayLength.ts +1 -2
  55. package/src/cramFile/codecs/external.ts +1 -1
  56. package/src/cramFile/codecs/huffman.ts +2 -1
  57. package/src/cramFile/container/compressionScheme.ts +1 -8
  58. package/src/cramFile/container/index.ts +21 -10
  59. package/src/cramFile/file.ts +28 -43
  60. package/src/cramFile/record.ts +1 -1
  61. package/src/cramFile/sectionParsers.ts +668 -390
  62. package/src/cramFile/slice/index.ts +11 -5
  63. package/src/cramFile/util.ts +90 -91
  64. package/src/typings/binary-parser.d.ts +0 -44
@@ -7,6 +7,7 @@ import CramRecord from '../record'
7
7
  import CramContainer from '../container'
8
8
  import CramFile, { CramFileBlock } from '../file'
9
9
  import {
10
+ getSectionParsers,
10
11
  isMappedSliceHeader,
11
12
  MappedSliceHeader,
12
13
  UnmappedSliceHeader,
@@ -191,10 +192,15 @@ export default class CramSlice {
191
192
  }
192
193
 
193
194
  // memoize
194
- async getHeader(): Promise<SliceHeader> {
195
+ async getHeader() {
195
196
  // fetch and parse the slice header
196
- const sectionParsers = await this.file.getSectionParsers()
197
+ const { majorVersion } = await this.file.getDefinition()
198
+ const sectionParsers = getSectionParsers(majorVersion)
197
199
  const containerHeader = await this.container.getHeader()
200
+ if (!containerHeader) {
201
+ throw new Error('no container header detected')
202
+ }
203
+
198
204
  const header = await this.file.readBlock(
199
205
  containerHeader._endPosition + this.containerPosition,
200
206
  )
@@ -230,7 +236,7 @@ export default class CramSlice {
230
236
  // read all the blocks into memory and store them
231
237
  let blockPosition = header._endPosition
232
238
  const blocks: CramFileBlock[] = new Array(header.parsedContent.numBlocks)
233
- for (let i = 0; i < blocks.length; i += 1) {
239
+ for (let i = 0; i < blocks.length; i++) {
234
240
  const block = await this.file.readBlock(blockPosition)
235
241
  if (block === undefined) {
236
242
  throw new Error('block undefined')
@@ -363,14 +369,14 @@ export default class CramSlice {
363
369
  this.file.options.checkSequenceMD5 &&
364
370
  isMappedSliceHeader(sliceHeader.parsedContent) &&
365
371
  sliceHeader.parsedContent.refSeqId >= 0 &&
366
- sliceHeader.parsedContent.md5.join('') !== '0000000000000000'
372
+ sliceHeader.parsedContent.md5?.join('') !== '0000000000000000'
367
373
  ) {
368
374
  const refRegion = await this.getReferenceRegion()
369
375
  if (refRegion) {
370
376
  const { seq, start, end } = refRegion
371
377
  const seqMd5 = sequenceMD5(seq)
372
378
  const storedMd5 = sliceHeader.parsedContent.md5
373
- .map(byte => (byte < 16 ? '0' : '') + byte.toString(16))
379
+ ?.map(byte => (byte < 16 ? '0' : '') + byte.toString(16))
374
380
  .join('')
375
381
  if (seqMd5 !== storedMd5) {
376
382
  throw new CramMalformedError(
@@ -1,5 +1,5 @@
1
1
  import md5 from 'md5'
2
- import { Parser } from '@gmod/binary-parser'
2
+ import Long from 'long'
3
3
  import { CramBufferOverrunError } from './codecs/getBits'
4
4
 
5
5
  export function itf8Size(v: number) {
@@ -18,10 +18,7 @@ export function itf8Size(v: number) {
18
18
  return 5
19
19
  }
20
20
 
21
- export function parseItf8(
22
- buffer: Uint8Array,
23
- initialOffset: number,
24
- ): [number, number] {
21
+ export function parseItf8(buffer: Uint8Array, initialOffset: number) {
25
22
  let offset = initialOffset
26
23
  const countFlags = buffer[offset]
27
24
  let result
@@ -60,106 +57,108 @@ export function parseItf8(
60
57
  'Attempted to read beyond end of buffer; this file seems truncated.',
61
58
  )
62
59
  }
63
- return [result, offset - initialOffset]
60
+ return [result, offset - initialOffset] as const
64
61
  }
65
62
 
66
- // parseLtf8(buffer, initialOffset) {
67
- // let offset = initialOffset
68
- // const countFlags = buffer[offset]
69
- // let result
70
- // if (countFlags < 0x80) {
71
- // result = countFlags
72
- // offset += 1
73
- // } else if (countFlags < 0xc0) {
74
- // result = ((buffer[offset] << 8) | buffer[offset + 1]) & 0x3fff
75
- // offset += 2
76
- // } else if (countFlags < 0xe0) {
77
- // result =
78
- // ((buffer[offset] << 16) |
79
- // (buffer[offset + 1] << 8) |
80
- // buffer[offset + 2]) &
81
- // 0x1fffff
82
- // offset += 3
83
- // } else if (countFlags < 0xf0) {
84
- // result =
85
- // ((buffer[offset] << 24) |
86
- // (buffer[offset + 1] << 16) |
87
- // (buffer[offset + 2] << 8) |
88
- // buffer[offset + 3]) &
89
- // 0x0fffffff
90
- // offset += 4
91
- // } else if (countFlags < 0xf8) {
92
- // result =
93
- // ((buffer[offset] & 15) * Math.pow(2,32) + (buffer[offset + 1] << 24)) |
94
- // ((buffer[offset + 2] << 16) |
95
- // (buffer[offset + 3] << 8) |
96
- // buffer[offset + 4])
97
- // // TODO *val_p = uv < 0x80000000UL ? uv : -((int32_t) (0xffffffffUL - uv)) - 1;
98
- // offset += 5
99
- // } else if (countFlags < 0xfc) {
100
- // result =
101
- // ((((buffer[offset] & 7) << 8) | buffer[offset + 1]) * Math.pow(2,32) +
102
- // (buffer[offset + 2] << 24)) |
103
- // ((buffer[offset + 3] << 16) |
104
- // (buffer[offset + 4] << 8) |
105
- // buffer[offset + 5])
106
- // offset += 6
107
- // } else if (countFlags < 0xfe) {
108
- // result =
109
- // ((((buffer[offset] & 3) << 16) |
110
- // (buffer[offset + 1] << 8) |
111
- // buffer[offset + 2]) *
112
- // Math.pow(2,32) +
113
- // (buffer[offset + 3] << 24)) |
114
- // ((buffer[offset + 4] << 16) |
115
- // (buffer[offset + 5] << 8) |
116
- // buffer[offset + 6])
117
- // offset += 7
118
- // } else if (countFlags < 0xff) {
119
- // result = Long.fromBytesBE(buffer.slice(offset + 1, offset + 8))
120
- // if (
121
- // result.greaterThan(Number.MAX_SAFE_INTEGER) ||
122
- // result.lessThan(Number.MIN_SAFE_INTEGER)
123
- // )
124
- // throw new CramUnimplementedError('integer overflow')
125
- // result = result.toNumber()
126
- // offset += 8
127
- // } else {
128
- // result = Long.fromBytesBE(buffer.slice(offset + 1, offset + 9))
129
- // if (
130
- // result.greaterThan(Number.MAX_SAFE_INTEGER) ||
131
- // result.lessThan(Number.MIN_SAFE_INTEGER)
132
- // )
133
- // throw new CramUnimplementedError('integer overflow')
134
- // result = result.toNumber()
135
- // offset += 9
136
- // }
137
- // return [result, offset - initialOffset]
138
- // },
139
-
140
- export type ParsedItem<T> = T & {
141
- _endPosition: number
142
- _size: number
63
+ export function parseLtf8(buffer: Buffer, initialOffset: number) {
64
+ let offset = initialOffset
65
+ const countFlags = buffer[offset]
66
+ let n
67
+ if (countFlags < 0x80) {
68
+ n = countFlags
69
+ offset += 1
70
+ } else if (countFlags < 0xc0) {
71
+ n = ((buffer[offset] << 8) | buffer[offset + 1]) & 0x3fff
72
+ offset += 2
73
+ } else if (countFlags < 0xe0) {
74
+ n =
75
+ ((buffer[offset] << 16) |
76
+ (buffer[offset + 1] << 8) |
77
+ buffer[offset + 2]) &
78
+ 0x1fffff
79
+ n = ((countFlags & 63) << 16) | buffer.readUInt16LE(offset + 1)
80
+ offset += 3
81
+ } else if (countFlags < 0xf0) {
82
+ n =
83
+ ((buffer[offset] << 24) |
84
+ (buffer[offset + 1] << 16) |
85
+ (buffer[offset + 2] << 8) |
86
+ buffer[offset + 3]) &
87
+ 0x0fffffff
88
+ offset += 4
89
+ } else if (countFlags < 0xf8) {
90
+ n =
91
+ ((buffer[offset] & 15) * Math.pow(2, 32) + (buffer[offset + 1] << 24)) |
92
+ ((buffer[offset + 2] << 16) |
93
+ (buffer[offset + 3] << 8) |
94
+ buffer[offset + 4])
95
+ // TODO *val_p = uv < 0x80000000UL ? uv : -((int32_t) (0xffffffffUL - uv)) - 1;
96
+ offset += 5
97
+ } else if (countFlags < 0xfc) {
98
+ n =
99
+ ((((buffer[offset] & 7) << 8) | buffer[offset + 1]) * Math.pow(2, 32) +
100
+ (buffer[offset + 2] << 24)) |
101
+ ((buffer[offset + 3] << 16) |
102
+ (buffer[offset + 4] << 8) |
103
+ buffer[offset + 5])
104
+ offset += 6
105
+ } else if (countFlags < 0xfe) {
106
+ n =
107
+ ((((buffer[offset] & 3) << 16) |
108
+ (buffer[offset + 1] << 8) |
109
+ buffer[offset + 2]) *
110
+ Math.pow(2, 32) +
111
+ (buffer[offset + 3] << 24)) |
112
+ ((buffer[offset + 4] << 16) |
113
+ (buffer[offset + 5] << 8) |
114
+ buffer[offset + 6])
115
+ offset += 7
116
+ } else if (countFlags < 0xff) {
117
+ n = Long.fromBytesBE(
118
+ buffer.slice(offset + 1, offset + 8) as unknown as number[],
119
+ )
120
+ if (
121
+ n.greaterThan(Number.MAX_SAFE_INTEGER) ||
122
+ n.lessThan(Number.MIN_SAFE_INTEGER)
123
+ ) {
124
+ throw new Error('integer overflow')
125
+ }
126
+ n = n.toNumber()
127
+ offset += 8
128
+ } else {
129
+ n = Long.fromBytesBE(
130
+ buffer.slice(offset + 1, offset + 9) as unknown as number[],
131
+ )
132
+ if (
133
+ n.greaterThan(Number.MAX_SAFE_INTEGER) ||
134
+ n.lessThan(Number.MIN_SAFE_INTEGER)
135
+ ) {
136
+ throw new Error('integer overflow')
137
+ }
138
+ n = n.toNumber()
139
+ offset += 9
140
+ }
141
+ return [n, offset - initialOffset] as const
143
142
  }
144
143
 
145
144
  export function parseItem<T>(
146
145
  buffer: Buffer,
147
- parser: Parser<T>,
146
+ parser: (buffer: Buffer, offset: number) => { offset: number; value: T },
148
147
  startBufferPosition = 0,
149
148
  startFilePosition = 0,
150
- ): ParsedItem<T> {
151
- const { offset, result } = parser.parse(buffer)
149
+ ) {
150
+ const { offset, value } = parser(buffer, startBufferPosition)
152
151
  return {
153
- ...result,
152
+ ...value,
154
153
  _endPosition: offset + startFilePosition,
155
154
  _size: offset - startBufferPosition,
156
155
  }
157
156
  }
158
157
 
159
- // this would be nice as a decorator, but i'm a little worried about
160
- // babel support for it going away or changing.
161
- // memoizes a method in the stupidest possible way, with no regard for the
162
- // arguments. actually, this only works on methods that take no arguments
158
+ // this would be nice as a decorator, but i'm a little worried about babel
159
+ // support for it going away or changing. memoizes a method in the stupidest
160
+ // possible way, with no regard for the arguments. actually, this only works
161
+ // on methods that take no arguments
163
162
  export function tinyMemoize(_class: any, methodName: any) {
164
163
  const method = _class.prototype[methodName]
165
164
  const memoAttrName = `_memo_${methodName}`
@@ -1,44 +0,0 @@
1
- declare module '@gmod/binary-parser' {
2
- export interface Options {
3
- stripNull?: boolean
4
- formatter?: (item: any) => any
5
- length?: number | string | ((this: { $parent: unknown }) => void)
6
- }
7
-
8
- export class Parser<T = unknown> {
9
- public static start<TStart>(): Parser<TStart>
10
-
11
- public uint8(name?: string | null, options?: Options): Parser
12
-
13
- public itf8(name?: string | null, options?: Options): Parser
14
-
15
- public ltf8(name?: string | null, options?: Options): Parser
16
-
17
- public uint32(name?: string | null, options?: Options): Parser
18
-
19
- public int32(name?: string | null, options?: Options): Parser
20
-
21
- public buffer(name?: string | null, options?: Options): Parser
22
-
23
- public string(name?: string | null, options?: Options): Parser
24
-
25
- public namely(name: string): Parser
26
-
27
- public nest(
28
- name?: string | null,
29
- options?: { type: Parser | string } & Options,
30
- ): Parser
31
-
32
- public choice(
33
- name?: string | null,
34
- options?: { tag: string; choices: any } & Options,
35
- ): Parser
36
-
37
- public array(
38
- name?: string | null,
39
- options?: { type: string | Parser } & Options,
40
- ): Parser
41
-
42
- parse(bytes: Buffer): { result: T; offset: number }
43
- }
44
- }