@cosyte/dicom 0.0.17 → 0.0.18

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.
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ var __export = (target, all) => {
9
9
  };
10
10
 
11
11
  // src/version.ts
12
- var VERSION = "0.0.17";
12
+ var VERSION = "0.0.18";
13
13
 
14
14
  // src/dictionary/index.ts
15
15
  var dictionary_exports = {};
@@ -11666,23 +11666,52 @@ var FATAL_CODES = {
11666
11666
  UNSUPPORTED_TRANSFER_SYNTAX: "UNSUPPORTED_TRANSFER_SYNTAX",
11667
11667
  EMPTY_INPUT: "EMPTY_INPUT"
11668
11668
  };
11669
+ var OFFSET_FRAMES = {
11670
+ /**
11671
+ * Byte 0 is byte 0 of the buffer handed to `parseDicom`. The only frame in
11672
+ * which indexing the caller's own input by `byteOffset` is meaningful.
11673
+ */
11674
+ INPUT: "input",
11675
+ /**
11676
+ * Byte 0 is byte 0 of the inflated Data Set of a Deflated Explicit VR LE
11677
+ * object (`1.2.840.10008.1.2.1.99`). The compressed input holds no such
11678
+ * byte, so the offset does not index it at any scale.
11679
+ */
11680
+ INFLATED_DATASET: "inflated-dataset",
11681
+ /**
11682
+ * Byte 0 is byte 0 of a slice this parser cut from inside a Value Field: a
11683
+ * defined-length Sequence Item's value, or an `SQ`/`UN` value handed to a
11684
+ * descent. **Where that slice begins is deliberately not published** - see
11685
+ * this table's own note.
11686
+ */
11687
+ VALUE_SLICE: "value-slice"
11688
+ };
11669
11689
  var DicomParseError = class extends Error {
11670
11690
  code;
11671
11691
  byteOffset;
11692
+ /**
11693
+ * The coordinate system {@link DicomParseError.byteOffset} is counted in.
11694
+ * See {@link OFFSET_FRAMES}.
11695
+ */
11696
+ offsetFrame;
11672
11697
  snippet;
11673
11698
  contextPath;
11674
11699
  /**
11675
11700
  * Construct a new `DicomParseError`. All fields except `contextPath` are
11676
- * required so every thrower populates positional context per `TOL-02`.
11701
+ * required so every thrower populates positional context per `TOL-02` - and
11702
+ * `offsetFrame` is required for the same reason `byteOffset` is, because an
11703
+ * offset whose frame is optional is an offset whose frame is usually
11704
+ * missing.
11677
11705
  *
11678
11706
  * @internal
11679
11707
  */
11680
- constructor(code, message, byteOffset, snippet, contextPath) {
11681
- const formatted = `[${code}] ${message} (offset=${String(byteOffset)})` + (contextPath !== void 0 && contextPath.length > 0 ? ` \u2026 in ${contextPath.join("/")}` : "");
11708
+ constructor(code, message, byteOffset, offsetFrame, snippet, contextPath) {
11709
+ const formatted = `[${code}] ${message} (offset=${String(byteOffset)} frame=${offsetFrame})` + (contextPath !== void 0 && contextPath.length > 0 ? ` \u2026 in ${contextPath.join("/")}` : "");
11682
11710
  super(formatted);
11683
11711
  this.name = "DicomParseError";
11684
11712
  this.code = code;
11685
11713
  this.byteOffset = byteOffset;
11714
+ this.offsetFrame = offsetFrame;
11686
11715
  this.snippet = snippet;
11687
11716
  this.contextPath = contextPath;
11688
11717
  }
@@ -11708,7 +11737,12 @@ function makeEmitter(ctx) {
11708
11737
  w.code,
11709
11738
  w.message,
11710
11739
  w.position.byteOffset,
11711
- buildSnippet(ctx.buffer, w.position.byteOffset),
11740
+ // Both come off the SAME frame object, so an escalation cannot name one
11741
+ // frame and cut its bytes from another. `DicomParseWarning.position`
11742
+ // itself carries no frame - that is `PRE-EXISTING` and stated on
11743
+ // `DicomPosition`, not closed here.
11744
+ ctx.frame.name,
11745
+ buildSnippet(ctx.frame.buffer, w.position.byteOffset),
11712
11746
  w.position.contextPath
11713
11747
  );
11714
11748
  };
@@ -11834,8 +11868,11 @@ var FATAL_MESSAGES = Object.freeze({
11834
11868
  message: "File Meta is truncated."
11835
11869
  },
11836
11870
  // The declared group length is deliberately absent. It is four bytes of the
11837
- // document read as a 32-bit integer, and this code fires precisely when those
11838
- // four bytes are not what they claim to be.
11871
+ // document read as a 32-bit integer. **NOT because this code fires only when
11872
+ // those four bytes are fabricated** - an honestly truncated file raises it
11873
+ // with a perfectly correct group length, measured - but because they are four
11874
+ // bytes a sender wrote in either reading, and in the other one they are part
11875
+ // of somebody's value.
11839
11876
  FILE_META_GROUP_LENGTH_OVERRUNS: {
11840
11877
  code: FATAL_CODES.INVALID_FILE_META,
11841
11878
  message: "(0002,0000) FileMetaInformationGroupLength declares more bytes than remain in the input. The declared length and the count of bytes that remain are withheld; the byte offset locates the group."
@@ -11920,88 +11957,89 @@ function renderTransferSyntax(ts) {
11920
11957
  function renderZlibCode(code) {
11921
11958
  return code !== void 0 && ZLIB_CODES.has(code) ? code : WITHHELD;
11922
11959
  }
11923
- function build(key, byteOffset, snippet, tokens = {}) {
11960
+ function build(key, byteOffset, offsetFrame, snippet, tokens = {}) {
11924
11961
  const entry = FATAL_MESSAGES[key];
11925
11962
  const message = entry.message.replace("{vr}", renderVr(tokens.vr)).replace("{ts}", renderTransferSyntax(tokens.ts)).replace("{zlib}", renderZlibCode(tokens.zlib)).replace("{n}", String(tokens.n ?? 0));
11926
- return new DicomParseError(entry.code, message, byteOffset, snippet);
11963
+ return new DicomParseError(entry.code, message, byteOffset, offsetFrame, snippet);
11927
11964
  }
11928
- function at(key, buffer, offset, tokens = {}) {
11929
- return build(key, offset, buildSnippet(buffer, offset), tokens);
11965
+ function at(key, frame, offset, tokens = {}) {
11966
+ return build(key, offset, frame.name, buildSnippet(frame.buffer, offset), tokens);
11930
11967
  }
11931
11968
  function emptyInput() {
11932
- return build("EMPTY_INPUT", 0, "");
11969
+ return build("EMPTY_INPUT", 0, OFFSET_FRAMES.INPUT, "");
11933
11970
  }
11934
11971
  function emptyInputAfterNormalization() {
11935
- return build("EMPTY_INPUT_AFTER_NORMALIZATION", 0, "");
11972
+ return build("EMPTY_INPUT_AFTER_NORMALIZATION", 0, OFFSET_FRAMES.INPUT, "");
11936
11973
  }
11937
- function notDicomPart10Required(buffer, offset) {
11938
- return at("NOT_DICOM_PART_10_REQUIRED", buffer, offset);
11974
+ function notDicomPart10Required(frame, offset) {
11975
+ return at("NOT_DICOM_PART_10_REQUIRED", frame, offset);
11939
11976
  }
11940
- function notDicomPart10(buffer, offset) {
11941
- return at("NOT_DICOM_PART_10", buffer, offset);
11977
+ function notDicomPart10(frame, offset) {
11978
+ return at("NOT_DICOM_PART_10", frame, offset);
11942
11979
  }
11943
- function unsupportedTransferSyntax(buffer, offset, ts) {
11980
+ function unsupportedTransferSyntax(frame, offset, ts) {
11944
11981
  const name = uid(ts)?.name ?? "";
11945
11982
  return build(
11946
11983
  "UNSUPPORTED_TRANSFER_SYNTAX",
11947
11984
  offset,
11948
- name.length > 0 ? name : buildSnippet(buffer, offset),
11985
+ frame.name,
11986
+ name.length > 0 ? name : buildSnippet(frame.buffer, offset),
11949
11987
  { ts }
11950
11988
  );
11951
11989
  }
11952
- function fileMetaTruncated(buffer, offset) {
11953
- return at("FILE_META_TRUNCATED", buffer, offset);
11990
+ function fileMetaTruncated(frame, offset) {
11991
+ return at("FILE_META_TRUNCATED", frame, offset);
11954
11992
  }
11955
- function fileMetaGroupLengthOverruns(buffer, offset) {
11956
- return at("FILE_META_GROUP_LENGTH_OVERRUNS", buffer, offset);
11993
+ function fileMetaGroupLengthOverruns(frame, offset) {
11994
+ return at("FILE_META_GROUP_LENGTH_OVERRUNS", frame, offset);
11957
11995
  }
11958
- function fileMetaTransferSyntaxMissing(buffer, offset) {
11959
- return at("FILE_META_TRANSFER_SYNTAX_MISSING", buffer, offset);
11996
+ function fileMetaTransferSyntaxMissing(frame, offset) {
11997
+ return at("FILE_META_TRANSFER_SYNTAX_MISSING", frame, offset);
11960
11998
  }
11961
- function truncatedDatasetHeader(buffer, offset) {
11962
- return at("TRUNCATED_DATASET_HEADER", buffer, offset);
11999
+ function truncatedDatasetHeader(frame, offset) {
12000
+ return at("TRUNCATED_DATASET_HEADER", frame, offset);
11963
12001
  }
11964
- function truncatedFffeHeader(buffer, offset) {
11965
- return at("TRUNCATED_FFFE_HEADER", buffer, offset);
12002
+ function truncatedFffeHeader(frame, offset) {
12003
+ return at("TRUNCATED_FFFE_HEADER", frame, offset);
11966
12004
  }
11967
- function truncatedExplicitVrHeader(buffer, offset) {
11968
- return at("TRUNCATED_EXPLICIT_VR_HEADER", buffer, offset);
12005
+ function truncatedExplicitVrHeader(frame, offset) {
12006
+ return at("TRUNCATED_EXPLICIT_VR_HEADER", frame, offset);
11969
12007
  }
11970
- function sqItemHeaderTruncated(buffer, offset) {
11971
- return at("SQ_ITEM_HEADER_TRUNCATED", buffer, offset);
12008
+ function sqItemHeaderTruncated(frame, offset) {
12009
+ return at("SQ_ITEM_HEADER_TRUNCATED", frame, offset);
11972
12010
  }
11973
- function unexpectedFffeAtDatasetLevel(buffer, offset) {
11974
- return at("UNEXPECTED_FFFE_AT_DATASET_LEVEL", buffer, offset);
12011
+ function unexpectedFffeAtDatasetLevel(frame, offset) {
12012
+ return at("UNEXPECTED_FFFE_AT_DATASET_LEVEL", frame, offset);
11975
12013
  }
11976
- function unexpectedFffeAtDatasetRoot(buffer, offset) {
11977
- return at("UNEXPECTED_FFFE_AT_DATASET_ROOT", buffer, offset);
12014
+ function unexpectedFffeAtDatasetRoot(frame, offset) {
12015
+ return at("UNEXPECTED_FFFE_AT_DATASET_ROOT", frame, offset);
11978
12016
  }
11979
- function undefinedLengthOnNonSqExplicit(buffer, offset, vr) {
11980
- return at("UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT", buffer, offset, { vr });
12017
+ function undefinedLengthOnNonSqExplicit(frame, offset, vr) {
12018
+ return at("UNDEFINED_LENGTH_ON_NON_SQ_EXPLICIT", frame, offset, { vr });
11981
12019
  }
11982
- function undefinedLengthOnNonSqImplicit(buffer, offset, vr) {
11983
- return at("UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT", buffer, offset, { vr });
12020
+ function undefinedLengthOnNonSqImplicit(frame, offset, vr) {
12021
+ return at("UNDEFINED_LENGTH_ON_NON_SQ_IMPLICIT", frame, offset, { vr });
11984
12022
  }
11985
- function elementLengthExceedsBuffer(buffer, offset) {
11986
- return at("ELEMENT_LENGTH_EXCEEDS_BUFFER", buffer, offset);
12023
+ function elementLengthExceedsBuffer(frame, offset) {
12024
+ return at("ELEMENT_LENGTH_EXCEEDS_BUFFER", frame, offset);
11987
12025
  }
11988
- function unexpectedTagInsideSequence(buffer, offset) {
11989
- return at("UNEXPECTED_TAG_INSIDE_SEQUENCE", buffer, offset);
12026
+ function unexpectedTagInsideSequence(frame, offset) {
12027
+ return at("UNEXPECTED_TAG_INSIDE_SEQUENCE", frame, offset);
11990
12028
  }
11991
- function encapsulatedFragmentExceedsBuffer(buffer, offset) {
11992
- return at("ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER", buffer, offset);
12029
+ function encapsulatedFragmentExceedsBuffer(frame, offset) {
12030
+ return at("ENCAPSULATED_FRAGMENT_EXCEEDS_BUFFER", frame, offset);
11993
12031
  }
11994
- function itemLengthExceedsBuffer(buffer, offset) {
11995
- return at("ITEM_LENGTH_EXCEEDS_BUFFER", buffer, offset);
12032
+ function itemLengthExceedsBuffer(frame, offset) {
12033
+ return at("ITEM_LENGTH_EXCEEDS_BUFFER", frame, offset);
11996
12034
  }
11997
- function sqNestingDepthExceeded(buffer, offset, limit) {
11998
- return at("SQ_NESTING_DEPTH_EXCEEDED", buffer, offset, { n: limit });
12035
+ function sqNestingDepthExceeded(frame, offset, limit) {
12036
+ return at("SQ_NESTING_DEPTH_EXCEEDED", frame, offset, { n: limit });
11999
12037
  }
12000
- function inflatedPayloadExceedsCap(buffer, offset, cap) {
12001
- return at("INFLATED_PAYLOAD_EXCEEDS_CAP", buffer, offset, { n: cap });
12038
+ function inflatedPayloadExceedsCap(frame, offset, cap) {
12039
+ return at("INFLATED_PAYLOAD_EXCEEDS_CAP", frame, offset, { n: cap });
12002
12040
  }
12003
- function inflateFailed(buffer, offset, code) {
12004
- return at("INFLATE_FAILED", buffer, offset, ...code !== void 0 ? [{ zlib: code }] : []);
12041
+ function inflateFailed(frame, offset, code) {
12042
+ return at("INFLATE_FAILED", frame, offset, ...code !== void 0 ? [{ zlib: code }] : []);
12005
12043
  }
12006
12044
  function copyValueBytes(src) {
12007
12045
  const out = Buffer.allocUnsafeSlow(src.length);
@@ -12634,7 +12672,7 @@ function parseFileMeta(buffer, datasetStart, ctx, emit) {
12634
12672
  firstElement = readExplicitLeElement(cursor);
12635
12673
  } catch (err) {
12636
12674
  if (err instanceof RangeError) {
12637
- throw fileMetaTruncated(buffer, fmStart);
12675
+ throw fileMetaTruncated(ctx.frame, fmStart);
12638
12676
  }
12639
12677
  throw err;
12640
12678
  }
@@ -12644,7 +12682,7 @@ function parseFileMeta(buffer, datasetStart, ctx, emit) {
12644
12682
  if (firstElement.tag === "00020000" && firstElement.vr === "UL" && firstElement.value.length === 4) {
12645
12683
  declaredFmLength = firstElement.value.readUInt32LE(0);
12646
12684
  if (cursor.position + declaredFmLength > buffer.length) {
12647
- throw fileMetaGroupLengthOverruns(buffer, fmStart);
12685
+ throw fileMetaGroupLengthOverruns(ctx.frame, fmStart);
12648
12686
  }
12649
12687
  } else {
12650
12688
  emit(fileMetaGroupLengthMissing({ byteOffset: fmStart, fileMeta: true }));
@@ -12661,7 +12699,7 @@ function parseFileMeta(buffer, datasetStart, ctx, emit) {
12661
12699
  next = readExplicitLeElement(cursor);
12662
12700
  } catch (err) {
12663
12701
  if (err instanceof RangeError) {
12664
- throw fileMetaTruncated(buffer, fmStart);
12702
+ throw fileMetaTruncated(ctx.frame, fmStart);
12665
12703
  }
12666
12704
  throw err;
12667
12705
  }
@@ -12685,7 +12723,7 @@ function parseFileMeta(buffer, datasetStart, ctx, emit) {
12685
12723
  next = readExplicitLeElement(cursor);
12686
12724
  } catch (err) {
12687
12725
  if (err instanceof RangeError) {
12688
- throw fileMetaTruncated(buffer, fmStart);
12726
+ throw fileMetaTruncated(ctx.frame, fmStart);
12689
12727
  }
12690
12728
  throw err;
12691
12729
  }
@@ -12704,7 +12742,7 @@ function parseFileMeta(buffer, datasetStart, ctx, emit) {
12704
12742
  }
12705
12743
  const tsElement = fmElements.find((e) => e.tag === "00020010");
12706
12744
  if (tsElement === void 0 || tsElement.vr !== "UI") {
12707
- throw fileMetaTransferSyntaxMissing(buffer, fmStart);
12745
+ throw fileMetaTransferSyntaxMissing(ctx.frame, fmStart);
12708
12746
  }
12709
12747
  const extraElements = fmElements.filter((e) => !MODELED_FM_TAGS.has(e.tag)).map((e) => Object.freeze({ tag: e.tag, vr: e.vr, value: Buffer.from(e.value) }));
12710
12748
  const fileMeta = {
@@ -12788,13 +12826,13 @@ function parsePart10Header(buffer, ctx, emit) {
12788
12826
  return { datasetStart: 132, hadPreamble: true };
12789
12827
  }
12790
12828
  if (ctx.stripPreamble === "require") {
12791
- throw notDicomPart10Required(buffer, 0);
12829
+ throw notDicomPart10Required(ctx.frame, 0);
12792
12830
  }
12793
12831
  if (looksLikeFileMetaGroupLengthAtOffsetZero(buffer)) {
12794
12832
  emit(missingPreamble({ byteOffset: 0 }));
12795
12833
  return { datasetStart: 0, hadPreamble: false };
12796
12834
  }
12797
- throw notDicomPart10(buffer, 0);
12835
+ throw notDicomPart10(ctx.frame, 0);
12798
12836
  }
12799
12837
  function looksLikeFileMetaGroupLengthAtOffsetZero(buffer) {
12800
12838
  if (buffer.length < 12) return false;
@@ -13205,7 +13243,7 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13205
13243
  ctx.nestingDepth += 1;
13206
13244
  if (ctx.nestingDepth > NESTING_DEPTH_LIMIT) {
13207
13245
  ctx.nestingDepth -= 1;
13208
- throw sqNestingDepthExceeded(buffer, valueStart, NESTING_DEPTH_LIMIT);
13246
+ throw sqNestingDepthExceeded(ctx.frame, valueStart, NESTING_DEPTH_LIMIT);
13209
13247
  }
13210
13248
  ctx.encodingContextStack.push(
13211
13249
  opts.encapsulatedPixelData === true ? "EncapsulatedPixelData" : "SqItem"
@@ -13241,7 +13279,7 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13241
13279
  itemLength = cursor.readUInt32();
13242
13280
  } catch (err) {
13243
13281
  if (err instanceof RangeError) {
13244
- throw sqItemHeaderTruncated(buffer, itemHeaderStart);
13282
+ throw sqItemHeaderTruncated(ctx.frame, itemHeaderStart);
13245
13283
  }
13246
13284
  throw err;
13247
13285
  }
@@ -13250,7 +13288,7 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13250
13288
  return { items, endOffset: cursor.position };
13251
13289
  }
13252
13290
  if (itemTag !== ITEM_TAG) {
13253
- throw unexpectedTagInsideSequence(buffer, itemHeaderStart);
13291
+ throw unexpectedTagInsideSequence(ctx.frame, itemHeaderStart);
13254
13292
  }
13255
13293
  if (itemLength === 0) {
13256
13294
  emit(emptyItemInSequence({ byteOffset: itemHeaderStart }, itemTag));
@@ -13266,7 +13304,7 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13266
13304
  }
13267
13305
  if (opts.encapsulatedPixelData === true) {
13268
13306
  if (cursor.position + itemLength > buffer.length) {
13269
- throw encapsulatedFragmentExceedsBuffer(buffer, itemHeaderStart);
13307
+ throw encapsulatedFragmentExceedsBuffer(ctx.frame, itemHeaderStart);
13270
13308
  }
13271
13309
  cursor.position += itemLength;
13272
13310
  items.push(new Item({ warnings: [], elements: /* @__PURE__ */ new Map(), index: itemIndex }));
@@ -13286,16 +13324,16 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
13286
13324
  emit(itemCrossesSequenceEnd({ byteOffset: itemHeaderStart }, itemTag));
13287
13325
  }
13288
13326
  if (cursor.position + itemLength > buffer.length) {
13289
- throw itemLengthExceedsBuffer(buffer, itemHeaderStart);
13327
+ throw itemLengthExceedsBuffer(ctx.frame, itemHeaderStart);
13290
13328
  }
13291
13329
  const itemSlice = buffer.subarray(cursor.position, cursor.position + itemLength);
13292
- const enclosingFrame = ctx.buffer;
13330
+ const enclosingFrame = ctx.frame;
13293
13331
  let inner;
13294
13332
  try {
13295
- ctx.buffer = itemSlice;
13333
+ ctx.frame = { buffer: itemSlice, name: OFFSET_FRAMES.VALUE_SLICE };
13296
13334
  inner = opts.innerStrategy(itemSlice, 0, ctx, emit);
13297
13335
  } finally {
13298
- ctx.buffer = enclosingFrame;
13336
+ ctx.frame = enclosingFrame;
13299
13337
  }
13300
13338
  items.push(new Item({ warnings: [], elements: inner.elements, index: itemIndex }));
13301
13339
  cursor.position += itemLength;
@@ -13320,17 +13358,17 @@ function tryParseDefinedLengthSQ(buffer, valueStart, valueLength, ctx, emit, imp
13320
13358
  const savedWarningsLen = ctx.warnings.length;
13321
13359
  try {
13322
13360
  const slice = buffer.subarray(valueStart, valueStart + valueLength);
13323
- const enclosingFrame = ctx.buffer;
13361
+ const enclosingFrame = ctx.frame;
13324
13362
  let result;
13325
13363
  try {
13326
- ctx.buffer = slice;
13364
+ ctx.frame = { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE };
13327
13365
  result = parseSequence(slice, 0, ctx, emit, {
13328
13366
  explicitLength: valueLength,
13329
13367
  littleEndian: true,
13330
13368
  innerStrategy: implicitLeInner
13331
13369
  });
13332
13370
  } finally {
13333
- ctx.buffer = enclosingFrame;
13371
+ ctx.frame = enclosingFrame;
13334
13372
  }
13335
13373
  return { success: true, items: result.items };
13336
13374
  } catch (err) {
@@ -13358,13 +13396,13 @@ function tryParseUnAsSQ(buffer, valueStart, valueLength, ctx, emit, implicitLeIn
13358
13396
  // CP-246: Implicit VR LE inner per D-30.
13359
13397
  innerStrategy: implicitLeInner
13360
13398
  };
13361
- const enclosingFrame = ctx.buffer;
13399
+ const enclosingFrame = ctx.frame;
13362
13400
  let result;
13363
13401
  try {
13364
- ctx.buffer = slice;
13402
+ ctx.frame = { buffer: slice, name: OFFSET_FRAMES.VALUE_SLICE };
13365
13403
  result = parseSequence(slice, 0, ctx, emit, opts);
13366
13404
  } finally {
13367
- ctx.buffer = enclosingFrame;
13405
+ ctx.frame = enclosingFrame;
13368
13406
  }
13369
13407
  emit(unParsedAsSQ({ byteOffset: valueStart }, tag));
13370
13408
  return {
@@ -13402,7 +13440,7 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
13402
13440
  length = cursor.readUInt32();
13403
13441
  } catch (err) {
13404
13442
  if (err instanceof RangeError) {
13405
- throw truncatedDatasetHeader(buffer, headerStart);
13443
+ throw truncatedDatasetHeader(ctx.frame, headerStart);
13406
13444
  }
13407
13445
  throw err;
13408
13446
  }
@@ -13411,7 +13449,7 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
13411
13449
  if (opts.stopOnItemDelim === true && tag === "FFFEE00D") {
13412
13450
  return { elements, endOffset: cursor.position };
13413
13451
  }
13414
- throw unexpectedFffeAtDatasetRoot(buffer, headerStart);
13452
+ throw unexpectedFffeAtDatasetRoot(ctx.frame, headerStart);
13415
13453
  }
13416
13454
  const position = { byteOffset: headerStart };
13417
13455
  const vr = resolveImplicitVR(tag, ctx, emit, position);
@@ -13478,10 +13516,10 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
13478
13516
  continue;
13479
13517
  }
13480
13518
  }
13481
- throw undefinedLengthOnNonSqImplicit(buffer, headerStart, vr);
13519
+ throw undefinedLengthOnNonSqImplicit(ctx.frame, headerStart, vr);
13482
13520
  }
13483
13521
  if (cursor.position + length > buffer.length) {
13484
- throw elementLengthExceedsBuffer(buffer, headerStart);
13522
+ throw elementLengthExceedsBuffer(ctx.frame, headerStart);
13485
13523
  }
13486
13524
  const valueStart = cursor.position;
13487
13525
  const valueEnd = valueStart + length;
@@ -13557,7 +13595,7 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
13557
13595
  peekGroup = cursor.readUInt16At(cursor.position);
13558
13596
  } catch (err) {
13559
13597
  if (err instanceof RangeError) {
13560
- throw truncatedDatasetHeader(buffer, headerStart);
13598
+ throw truncatedDatasetHeader(ctx.frame, headerStart);
13561
13599
  }
13562
13600
  throw err;
13563
13601
  }
@@ -13570,7 +13608,7 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
13570
13608
  cursor.readUInt32();
13571
13609
  } catch (err) {
13572
13610
  if (err instanceof RangeError) {
13573
- throw truncatedFffeHeader(buffer, headerStart);
13611
+ throw truncatedFffeHeader(ctx.frame, headerStart);
13574
13612
  }
13575
13613
  throw err;
13576
13614
  }
@@ -13578,14 +13616,14 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
13578
13616
  if (opts.stopOnItemDelim === true && fffeTag === "FFFEE00D") {
13579
13617
  return { elements, endOffset: cursor.position };
13580
13618
  }
13581
- throw unexpectedFffeAtDatasetLevel(buffer, headerStart);
13619
+ throw unexpectedFffeAtDatasetLevel(ctx.frame, headerStart);
13582
13620
  }
13583
13621
  let header;
13584
13622
  try {
13585
13623
  header = readExplicitElementHeader(cursor, ctx, emit);
13586
13624
  } catch (err) {
13587
13625
  if (err instanceof RangeError) {
13588
- throw truncatedExplicitVrHeader(buffer, headerStart);
13626
+ throw truncatedExplicitVrHeader(ctx.frame, headerStart);
13589
13627
  }
13590
13628
  throw err;
13591
13629
  }
@@ -13725,10 +13763,10 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
13725
13763
  continue;
13726
13764
  }
13727
13765
  if (length === UNDEFINED_LENGTH2) {
13728
- throw undefinedLengthOnNonSqExplicit(buffer, headerStart, vr);
13766
+ throw undefinedLengthOnNonSqExplicit(ctx.frame, headerStart, vr);
13729
13767
  }
13730
13768
  if (cursor.position + length > buffer.length) {
13731
- throw elementLengthExceedsBuffer(buffer, headerStart);
13769
+ throw elementLengthExceedsBuffer(ctx.frame, headerStart);
13732
13770
  }
13733
13771
  const valueStart = cursor.position;
13734
13772
  const valueEnd = valueStart + length;
@@ -13789,11 +13827,14 @@ function parseDeflatedLEWithCap(buffer, datasetStart, ctx, emit, maxInflatedByte
13789
13827
  const code = errAny.code;
13790
13828
  const message = errAny.message ?? String(err);
13791
13829
  if (code === "ERR_BUFFER_TOO_LARGE" || err instanceof RangeError && /maxOutputLength|too large/i.test(message)) {
13792
- throw inflatedPayloadExceedsCap(buffer, datasetStart, maxInflatedBytes);
13830
+ throw inflatedPayloadExceedsCap(ctx.frame, datasetStart, maxInflatedBytes);
13793
13831
  }
13794
- throw inflateFailed(buffer, datasetStart, code);
13832
+ throw inflateFailed(ctx.frame, datasetStart, code);
13795
13833
  }
13796
- const innerCtx = { ...ctx, buffer: inflated };
13834
+ const innerCtx = {
13835
+ ...ctx,
13836
+ frame: { buffer: inflated, name: OFFSET_FRAMES.INFLATED_DATASET }
13837
+ };
13797
13838
  const innerChokepoint = makeEmitter(innerCtx);
13798
13839
  const innerEmit = (w) => {
13799
13840
  const wrapped = {
@@ -13843,7 +13884,7 @@ function parseDicom(input, options = {}) {
13843
13884
  const tsUid = fileMeta.transferSyntaxUID;
13844
13885
  const strategy = TRANSFER_SYNTAX_PARSERS[tsUid];
13845
13886
  if (strategy === void 0) {
13846
- throw unsupportedTransferSyntax(buffer, fileMetaEnd, tsUid);
13887
+ throw unsupportedTransferSyntax(ctx.frame, fileMetaEnd, tsUid);
13847
13888
  }
13848
13889
  const { elements } = strategy(buffer, fileMetaEnd, ctx, emit);
13849
13890
  return new Dataset({ fileMeta, warnings: ctx.warnings, elements });
@@ -13861,7 +13902,9 @@ function normalizeInput(input) {
13861
13902
  }
13862
13903
  function buildContext(buffer, options, warnings) {
13863
13904
  const base = {
13864
- buffer,
13905
+ // The root frame. Every nested frame is entered from here by a swap that
13906
+ // moves the bytes and the name together; see `ParseFrame`.
13907
+ frame: { buffer, name: OFFSET_FRAMES.INPUT },
13865
13908
  strict: options.strict === true,
13866
13909
  stripPreamble: options.stripPreamble ?? "tolerate",
13867
13910
  warnings,
@@ -15898,6 +15941,6 @@ function deidentify(ds, options = {}) {
15898
15941
  return { dataset, report };
15899
15942
  }
15900
15943
 
15901
- export { CODING_SCHEME_OIDS, DEFAULT_UID_ROOT, DEIDENTIFY_ERROR_CODES, DEIDENTIFY_OPTIONS, Dataset, DeidentifyError, DicomParseError, DicomSerializeError, DicomValueError, dictionary_exports as Dictionary, Element, FATAL_CODES, Item, ProfileDefinitionError, SERIALIZE_ERROR_CODES, Sequence, VALUE_ERROR_CODES, VERSION, WARNING_CODES, codingSchemeOid, decodeElementValue, decodeText, defineProfile, deidentify, isKnownCharsetTerm, makeUidRemapper, parseDate, parseDateTime, parseDicom, parsePersonName, parseSpecificCharacterSet, parseTime, profiles, readCode, resolveDecoderLabel, serializeDicom };
15944
+ export { CODING_SCHEME_OIDS, DEFAULT_UID_ROOT, DEIDENTIFY_ERROR_CODES, DEIDENTIFY_OPTIONS, Dataset, DeidentifyError, DicomParseError, DicomSerializeError, DicomValueError, dictionary_exports as Dictionary, Element, FATAL_CODES, Item, OFFSET_FRAMES, ProfileDefinitionError, SERIALIZE_ERROR_CODES, Sequence, VALUE_ERROR_CODES, VERSION, WARNING_CODES, codingSchemeOid, decodeElementValue, decodeText, defineProfile, deidentify, isKnownCharsetTerm, makeUidRemapper, parseDate, parseDateTime, parseDicom, parsePersonName, parseSpecificCharacterSet, parseTime, profiles, readCode, resolveDecoderLabel, serializeDicom };
15902
15945
  //# sourceMappingURL=index.mjs.map
15903
15946
  //# sourceMappingURL=index.mjs.map