All files / metadata/src/utilities/metadataProvider naturalizedHandlers.ts

91.66% Statements 33/36
63.63% Branches 14/22
100% Functions 6/6
91.66% Lines 33/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110            128x   128x 128x               45x 45x                 45x 45x           45x               10611x 10611x 10611x 10611x 10611x                   45x 45x 45x   45x 45x 45x   45x 45x 45x 45x         45x               10656x 10656x 10611x     45x 45x 45x                       384x     384x     384x        
import dcmjs from 'dcmjs';
import { MetadataModules } from '../../enums';
import { addAddProvider, addTypedProvider } from '../../metaData';
import { MetaDataIterator, NaturalTagListener } from '../dicomStream';
import { baseImageIdQueryFilter } from './imageIdsProviders';
 
const { AsyncDicomReader } = dcmjs.async;
 
const NATURAL_BASE_IMAGE_ID_FILTER_PRIORITY = 60_000;
const NATURALIZED_ADD_HANDLER_PRIORITY = 30_000;
 
type Part10Input =
  | ArrayBuffer
  | Uint8Array
  | (() => ArrayBuffer | Uint8Array | Promise<ArrayBuffer | Uint8Array>);
 
function toArrayBuffer(part10Value: ArrayBuffer | Uint8Array): ArrayBuffer {
  Eif (part10Value instanceof ArrayBuffer) {
    return part10Value;
  }
  return part10Value.buffer.slice(
    part10Value.byteOffset,
    part10Value.byteOffset + part10Value.byteLength
  );
}
 
async function resolvePart10Input(part10: Part10Input): Promise<ArrayBuffer> {
  const resolvedValue = typeof part10 === 'function' ? await part10() : part10;
  Iif (
    !(resolvedValue instanceof ArrayBuffer) &&
    !(resolvedValue instanceof Uint8Array)
  ) {
    throw new Error('part10 must resolve to ArrayBuffer or Uint8Array');
  }
  return toArrayBuffer(resolvedValue);
}
 
/**
 * Converts DICOMweb JSON-style metadata into a NATURALIZED object
 * using the standard metadata iterator/listener pipeline.
 */
export function naturalizeDicomwebMetadata(metadata: Record<string, unknown>) {
  const iterator = new MetaDataIterator(metadata);
  const listener = NaturalTagListener.createMetadataListener();
  listener.startObject();
  iterator.syncIterator(listener);
  return listener.pop();
}
 
/**
 * Naturalizes a Part10 payload into a DICOM dictionary-like object.
 *
 * Supports direct binary input or a lazy resolver function and preserves
 * transfer syntax information on the returned naturalized object.
 */
export async function naturalizePart10Buffer(part10: Part10Input) {
  const arrayBuffer = await resolvePart10Input(part10);
  const reader = new AsyncDicomReader();
  const listener = NaturalTagListener.createMetadataListener();
 
  reader.stream.addBuffer(arrayBuffer);
  reader.stream.setComplete();
  await reader.readFile({ listener });
 
  const naturalized = reader.dict;
  const transferSyntaxUid = reader.syntax;
  Eif (transferSyntaxUid) {
    naturalized.TransferSyntaxUID = Array.isArray(transferSyntaxUid)
      ? transferSyntaxUid[0]
      : transferSyntaxUid;
  }
 
  return naturalized;
}
 
/**
 * Add-path NATURALIZED provider that handles sync `{ dicomwebJson }` and async
 * `{ part10Buffer }` ingestion.
 */
function naturalizedAddProvider(next, query: string, data, options) {
  const dicomwebJson = options?.dicomwebJson ?? options?.metadata;
  if (dicomwebJson && typeof dicomwebJson === 'object') {
    return naturalizeDicomwebMetadata(dicomwebJson as Record<string, unknown>);
  }
 
  const part10Buffer = options?.part10Buffer ?? options?.part10;
  Eif (part10Buffer) {
    return naturalizePart10Buffer(part10Buffer as Part10Input);
  }
 
  return next(query, data, options);
}
 
/**
 * Registers NATURALIZED-related handlers for read and add paths:
 * - base-image-id query normalization filter
 * - sync/async ingestion through add-path providers
 */
export function registerNaturalizedHandlers() {
  addTypedProvider(MetadataModules.NATURALIZED, baseImageIdQueryFilter, {
    priority: NATURAL_BASE_IMAGE_ID_FILTER_PRIORITY,
  });
  addAddProvider(MetadataModules.NATURALIZED, baseImageIdQueryFilter, {
    priority: NATURAL_BASE_IMAGE_ID_FILTER_PRIORITY,
  });
  addAddProvider(MetadataModules.NATURALIZED, naturalizedAddProvider, {
    priority: NATURALIZED_ADD_HANDLER_PRIORITY,
  });
}