All files / dicomImageLoader/src/imageLoader/wadors extractMultipart.ts

90.47% Statements 38/42
54.16% Branches 13/24
100% Functions 4/4
89.74% Lines 35/39

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 111 112 113 114      428x                                   9454x   9454x 9454x 9454x                   9454x     9454x   9454x       9454x 9454x   9454x 9454x   9454x       9454x     9454x   9454x       9454x   9454x 9454x 9454x 9454x 9454x     9454x                             9454x 9454x 9454x           9454x 18908x 9454x           9454x 9454x 9454x   9454x 1056990x     9454x    
import { Enums } from '@cornerstonejs/core';
import findIndexOfString from './findIndexOfString';
 
const { ImageQualityStatus } = Enums;
/**
 * Extracts multipart/related data or single part data from a response byte
 * array.
 *
 * @param contentType - guess of the root content type
 * @param imageFrameAsArrayBuffer - array buffer containing the image frame
 * @param options - contains already computed values from
 *        earlier calls, allowing additional calls to be made to fetch
 *        additional data.
 * @param isPartial - indicates the file may end partially
 * @returns a compressed image frame containing the pixel data.
 */
export default function extractMultipart(
  contentType: string,
  imageFrameAsArrayBuffer,
  options?
) {
  options ||= {};
  // request succeeded, Parse the multi-part mime response
  const response = new Uint8Array(imageFrameAsArrayBuffer);
  const isPartial = !!options?.isPartial;
  Iif (contentType.indexOf('multipart') === -1) {
    return {
      contentType,
      imageQualityStatus: isPartial
        ? ImageQualityStatus.SUBRESOLUTION
        : ImageQualityStatus.FULL_RESOLUTION,
      pixelData: response,
    };
  }
 
  let { tokenIndex, responseHeaders, boundary, multipartContentType } = options;
 
  // First look for the multipart mime header
  tokenIndex ||= findIndexOfString(response, '\r\n\r\n');
 
  Iif (tokenIndex === -1) {
    throw new Error('invalid response - no multipart mime header');
  }
 
  Eif (!boundary) {
    const header = uint8ArrayToString(response, 0, tokenIndex);
    // Now find the boundary  marker
    responseHeaders = header.split('\r\n');
    boundary = findBoundary(responseHeaders);
 
    Iif (!boundary) {
      throw new Error('invalid response - no boundary marker');
    }
  }
  const offset = tokenIndex + 4; // skip over the \r\n\r\n
 
  // find the terminal boundary marker
  const endIndex = findIndexOfString(response, boundary, offset);
 
  Iif (endIndex === -1 && !isPartial) {
    throw new Error('invalid response - terminating boundary not found');
  }
 
  multipartContentType ||= findContentType(responseHeaders);
 
  options.tokenIndex = tokenIndex;
  options.boundary = boundary;
  options.responseHeaders = responseHeaders;
  options.multipartContentType = multipartContentType;
  options.isPartial = endIndex === -1;
 
  // return the info for this pixel data
  return {
    contentType: multipartContentType,
    // done indicates if the read has finished the entire image, not if
    // the image is completely available
    extractDone: !isPartial || endIndex !== -1,
    tokenIndex,
    responseHeaders,
    boundary,
    multipartContentType,
    // Exclude the \r\n as well as the boundary
    pixelData: imageFrameAsArrayBuffer.slice(offset, endIndex - 2),
  };
}
 
export function findBoundary(header: string[]): string {
  for (let i = 0; i < header.length; i++) {
    Eif (header[i].substr(0, 2) === '--') {
      return header[i];
    }
  }
}
 
export function findContentType(header: string[]): string {
  for (let i = 0; i < header.length; i++) {
    if (header[i].substr(0, 13) === 'Content-Type:') {
      return header[i].substr(13).trim();
    }
  }
}
 
export function uint8ArrayToString(data, offset, length) {
  offset = offset || 0;
  length = length || data.length - offset;
  let str = '';
 
  for (let i = offset; i < offset + length; i++) {
    str += String.fromCharCode(data[i]);
  }
 
  return str;
}