@flighthq/texture-formats 0.3.0-next.906.07cea63 → 0.3.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.
@@ -1,8 +1,9 @@
1
- export * from './detectTextureContainer';
2
- export * from './parseAtf';
3
- export * from './parseBasis';
4
- export * from './parseDds';
5
- export * from './parseKtx2';
6
- export * from './selectTextureContainer';
7
- export * from './textureLevelLayout';
1
+ export { detectTextureContainer } from './detectTextureContainer';
2
+ export { explainTextureContainerParse } from './explainTextureContainerParse';
3
+ export { parseAtf } from './parseAtf';
4
+ export { parseBasis } from './parseBasis';
5
+ export { parseDds } from './parseDds';
6
+ export { parseKtx2 } from './parseKtx2';
7
+ export { selectTextureContainer } from './selectTextureContainer';
8
+ export { computeTextureContainerLevels, getTextureContainerLevelByteLength } from './textureLevelLayout';
8
9
  //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,kCAAkC,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/contract.js CHANGED
@@ -1,8 +1,9 @@
1
- export * from './detectTextureContainer';
2
- export * from './parseAtf';
3
- export * from './parseBasis';
4
- export * from './parseDds';
5
- export * from './parseKtx2';
6
- export * from './selectTextureContainer';
7
- export * from './textureLevelLayout';
1
+ export { detectTextureContainer } from './detectTextureContainer';
2
+ export { explainTextureContainerParse } from './explainTextureContainerParse';
3
+ export { parseAtf } from './parseAtf';
4
+ export { parseBasis } from './parseBasis';
5
+ export { parseDds } from './parseDds';
6
+ export { parseKtx2 } from './parseKtx2';
7
+ export { selectTextureContainer } from './selectTextureContainer';
8
+ export { computeTextureContainerLevels, getTextureContainerLevelByteLength } from './textureLevelLayout';
8
9
  //# sourceMappingURL=contract.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,kCAAkC,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,2 +1,3 @@
1
- export declare function detectTextureContainer(bytes: Readonly<Uint8Array>): 'atf' | 'basis' | 'dds' | 'ktx2' | null;
1
+ import type { TextureContainerKind } from '@flighthq/types/contract';
2
+ export declare function detectTextureContainer(bytes: Readonly<Uint8Array>): TextureContainerKind | null;
2
3
  //# sourceMappingURL=detectTextureContainer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"detectTextureContainer.d.ts","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"AAMA,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,CAW3G"}
1
+ {"version":3,"file":"detectTextureContainer.d.ts","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAErE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,oBAAoB,GAAG,IAAI,CAW/F"}
@@ -1,9 +1,3 @@
1
- // Sniffs which GPU texture container a byte buffer holds from its magic bytes — `'ktx2'`, `'dds'`,
2
- // `'basis'`, `'atf'`, or `null` when the header is too short or unrecognized. The texture-container
3
- // sibling of `detectImageMimeType`: a cheap dispatcher to pick a `parse*` function without fully
4
- // parsing, and the single point of container identification in the SDK. `'atf'` alone maps to the
5
- // array-returning `parseAtf` (an ATF holds one-or-more peer encodings); the others map to a single
6
- // `parse*` returning one `TextureContainer`.
7
1
  export function detectTextureContainer(bytes) {
8
2
  if (bytes.byteLength >= 12 && isKtx2Magic(bytes))
9
3
  return 'ktx2';
@@ -1 +1 @@
1
- {"version":3,"file":"detectTextureContainer.js","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,oGAAoG;AACpG,iGAAiG;AACjG,kGAAkG;AAClG,mGAAmG;AACnG,6CAA6C;AAC7C,MAAM,UAAU,sBAAsB,CAAC,KAA2B;IAChE,IAAI,KAAK,CAAC,UAAU,IAAI,EAAE,IAAI,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAChE,oCAAoC;IACpC,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9G,OAAO,KAAK,CAAC;IACf,CAAC;IACD,8BAA8B;IAC9B,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACvG,mDAAmD;IACnD,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IACpF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,KAA2B;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qBAAqB;AACrB,MAAM,SAAS,GAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"detectTextureContainer.js","sourceRoot":"","sources":["../src/detectTextureContainer.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,sBAAsB,CAAC,KAA2B;IAChE,IAAI,KAAK,CAAC,UAAU,IAAI,EAAE,IAAI,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAChE,oCAAoC;IACpC,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9G,OAAO,KAAK,CAAC;IACf,CAAC;IACD,8BAA8B;IAC9B,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACvG,mDAAmD;IACnD,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IACpF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,KAA2B;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qBAAqB;AACrB,MAAM,SAAS,GAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TextureContainerParseExplanation } from '@flighthq/types/contract';
2
+ export declare function explainTextureContainerParse(bytes: Readonly<Uint8Array>): TextureContainerParseExplanation | null;
3
+ //# sourceMappingURL=explainTextureContainerParse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainTextureContainerParse.d.ts","sourceRoot":"","sources":["../src/explainTextureContainerParse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAUjF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gCAAgC,GAAG,IAAI,CAMjH"}
@@ -0,0 +1,27 @@
1
+ import { detectTextureContainer } from './detectTextureContainer';
2
+ import { getAtfParseFailureReason } from './parseAtf';
3
+ import { getBasisParseFailureReason } from './parseBasis';
4
+ import { getDdsParseFailureReason } from './parseDds';
5
+ import { getKtx2ParseFailureReason } from './parseKtx2';
6
+ // Explains why the detected texture container's parser would return null. Returns null when parsing
7
+ // succeeds. The query does not retain payload bytes or expose parser-internal reader state.
8
+ export function explainTextureContainerParse(bytes) {
9
+ const container = detectTextureContainer(bytes);
10
+ if (container === null)
11
+ return { container: null, reason: 'container-unrecognized' };
12
+ const reason = getParseFailureReason(container, bytes);
13
+ return reason === null ? null : { container, reason };
14
+ }
15
+ function getParseFailureReason(container, bytes) {
16
+ switch (container) {
17
+ case 'atf':
18
+ return getAtfParseFailureReason(bytes);
19
+ case 'basis':
20
+ return getBasisParseFailureReason(bytes);
21
+ case 'dds':
22
+ return getDdsParseFailureReason(bytes);
23
+ case 'ktx2':
24
+ return getKtx2ParseFailureReason(bytes);
25
+ }
26
+ }
27
+ //# sourceMappingURL=explainTextureContainerParse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainTextureContainerParse.js","sourceRoot":"","sources":["../src/explainTextureContainerParse.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,oGAAoG;AACpG,4FAA4F;AAC5F,MAAM,UAAU,4BAA4B,CAAC,KAA2B;IACtE,MAAM,SAAS,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;IAErF,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACvD,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACxD,CAAC;AAED,SAAS,qBAAqB,CAC5B,SAAqE,EACrE,KAA2B;IAE3B,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,KAAK;YACR,OAAO,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACzC,KAAK,OAAO;YACV,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC;QAC3C,KAAK,KAAK;YACR,OAAO,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACzC,KAAK,MAAM;YACT,OAAO,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { computeTextureContainerLevels, detectTextureContainer, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
1
+ export { computeTextureContainerLevels, detectTextureContainer, explainTextureContainerParse, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,4BAA4B,EAC5B,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { computeTextureContainerLevels, detectTextureContainer, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
1
+ export { computeTextureContainerLevels, detectTextureContainer, explainTextureContainerParse, getTextureContainerLevelByteLength, parseAtf, parseBasis, parseDds, parseKtx2, selectTextureContainer, } from './contract';
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,4BAA4B,EAC5B,kCAAkC,EAClC,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
@@ -1,3 +1,5 @@
1
1
  import type { TextureContainer } from '@flighthq/types/contract';
2
+ import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
3
+ export declare function getAtfParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
2
4
  export declare function parseAtf(bytes: Readonly<Uint8Array>): TextureContainer[] | null;
3
5
  //# sourceMappingURL=parseAtf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseAtf.d.ts","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAsCjE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAqF/E"}
1
+ {"version":3,"file":"parseAtf.d.ts","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AASnF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAI/G;AA6BD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAE/E"}
package/dist/parseAtf.js CHANGED
@@ -1,4 +1,9 @@
1
1
  import { createByteReader, hasByteReaderBytes, readByteReaderU24BigEndian, readByteReaderU32BigEndian, } from './byteReader';
2
+ export function getAtfParseFailureReason(bytes) {
3
+ const failure = { reason: null };
4
+ const containers = parseAtfInternal(bytes, failure);
5
+ return containers === null ? failure.reason : null;
6
+ }
2
7
  // Parses an ATF (Adobe Texture Format) container into an ARRAY of peer `TextureContainer`s, or returns
3
8
  // `null` if the bytes are not ATF, are truncated, or carry an unsupported ATF format code. ATF is the
4
9
  // Flash/Stage3D/AIR GPU-texture container (an OpenFL/Lime feature target). Unlike KTX2/DDS/Basis, a
@@ -27,12 +32,15 @@ import { createByteReader, hasByteReaderBytes, readByteReaderU24BigEndian, readB
27
32
  // 4/5/13 with alpha); the raw-BGRA codes (0/1) and the JPEG-XR/LZMA-wrapped variants are unsupported and
28
33
  // return `null`.
29
34
  export function parseAtf(bytes) {
35
+ return parseAtfInternal(bytes);
36
+ }
37
+ function parseAtfInternal(bytes, failure) {
30
38
  if (!hasAtfSignature(bytes))
31
- return null;
39
+ return reject(failure, 'container-unrecognized');
32
40
  const versioned = bytes[6] === atfNewVersionMarker;
33
41
  const headerOffset = versioned ? atfNewHeaderOffset : atfLegacyHeaderOffset;
34
42
  if (bytes.byteLength < headerOffset + 4)
35
- return null;
43
+ return reject(failure, 'header-truncated');
36
44
  // `version` selects the block-length width (u24 for the legacy version-0 layout, u32 otherwise) and
37
45
  // whether an ETC2 slot follows the DXT/ETC1/PVRTC trio.
38
46
  const version = versioned ? bytes[7] : 0;
@@ -41,19 +49,21 @@ export function parseAtf(bytes) {
41
49
  const lengthReader = createByteReader(bytes, versioned ? 8 : 3);
42
50
  const payloadLength = versioned ? readByteReaderU32BigEndian(lengthReader) : readByteReaderU24BigEndian(lengthReader);
43
51
  if (headerOffset + payloadLength > bytes.byteLength)
44
- return null;
52
+ return reject(failure, 'level-range-out-of-bounds');
45
53
  const typeFormatByte = bytes[headerOffset];
46
54
  const log2Width = bytes[headerOffset + 1];
47
55
  const log2Height = bytes[headerOffset + 2];
48
56
  const mipCount = bytes[headerOffset + 3];
49
57
  const formatCode = typeFormatByte & atfFormatCodeMask;
50
58
  const alpha = atfAlphaFormatCodes.has(formatCode);
51
- if (!alpha && !atfOpaqueFormatCodes.has(formatCode))
52
- return null; // raw-BGRA / JPEG-XR / LZMA — unsupported
53
- if (log2Width > atfMaxLog2Dimension || log2Height > atfMaxLog2Dimension)
54
- return null;
59
+ if (!alpha && !atfOpaqueFormatCodes.has(formatCode)) {
60
+ return reject(failure, 'format-unsupported'); // raw-BGRA / JPEG-XR / LZMA — unsupported
61
+ }
62
+ if (log2Width > atfMaxLog2Dimension || log2Height > atfMaxLog2Dimension) {
63
+ return reject(failure, 'structure-invalid');
64
+ }
55
65
  if (mipCount < 1)
56
- return null;
66
+ return reject(failure, 'structure-invalid');
57
67
  const cube = (typeFormatByte & atfCubeFlag) !== 0;
58
68
  const faces = cube ? 6 : 1;
59
69
  const width = 1 << log2Width;
@@ -72,10 +82,10 @@ export function parseAtf(bytes) {
72
82
  for (let level = 0; level < mipCount; level += 1) {
73
83
  for (let slot = 0; slot < slotCount; slot += 1) {
74
84
  if (!hasByteReaderBytes(reader, lengthWidth))
75
- return null;
85
+ return reject(failure, 'level-range-out-of-bounds');
76
86
  const blockLength = version === 0 ? readByteReaderU24BigEndian(reader) : readByteReaderU32BigEndian(reader);
77
87
  if (!hasByteReaderBytes(reader, blockLength))
78
- return null;
88
+ return reject(failure, 'level-range-out-of-bounds');
79
89
  if (blockLength === 0)
80
90
  continue; // absent encoding for this (side, level)
81
91
  const byteOffset = reader.offset;
@@ -111,12 +121,17 @@ export function parseAtf(bytes) {
111
121
  });
112
122
  }
113
123
  if (containers.length === 0)
114
- return null;
124
+ return reject(failure, 'structure-invalid');
115
125
  return containers;
116
126
  }
127
+ function reject(failure, reason) {
128
+ if (failure !== undefined)
129
+ failure.reason = reason;
130
+ return null;
131
+ }
117
132
  function hasAtfSignature(bytes) {
118
- // 'ATF' — 0x41 0x54 0x46. Seven bytes is the shortest header that can carry the version marker at 6.
119
- return bytes.byteLength >= 7 && bytes[0] === 0x41 && bytes[1] === 0x54 && bytes[2] === 0x46;
133
+ // 'ATF' — 0x41 0x54 0x46. Header length is validated separately after container detection.
134
+ return bytes.byteLength >= 3 && bytes[0] === 0x41 && bytes[1] === 0x54 && bytes[2] === 0x46;
120
135
  }
121
136
  const atfCubeFlag = 0x80;
122
137
  const atfFormatCodeMask = 0x7f;
@@ -1 +1 @@
1
- {"version":3,"file":"parseAtf.js","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parseAtf.js","sourceRoot":"","sources":["../src/parseAtf.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
1
  import type { TextureContainer } from '@flighthq/types/contract';
2
+ import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
3
+ export declare function getBasisParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
2
4
  export declare function parseBasis(bytes: Readonly<Uint8Array>): TextureContainer | null;
3
5
  //# sourceMappingURL=parseBasis.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseBasis.d.ts","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA0BjE,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAuD/E"}
1
+ {"version":3,"file":"parseBasis.d.ts","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAWnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAIjH;AAeD,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAE/E"}
@@ -1,4 +1,9 @@
1
1
  import { createByteReader, hasByteReaderBytes, readByteReaderU16, readByteReaderU24, readByteReaderU32, readByteReaderU8, } from './byteReader';
2
+ export function getBasisParseFailureReason(bytes) {
3
+ const failure = { reason: null };
4
+ const container = parseBasisInternal(bytes, failure);
5
+ return container === null ? failure.reason : null;
6
+ }
2
7
  // Parses a Basis Universal `.basis` container into a `TextureContainer`, or returns `null` if the bytes
3
8
  // are not a `.basis` file, are truncated, or carry an unknown texture format.
4
9
  //
@@ -13,26 +18,30 @@ import { createByteReader, hasByteReaderBytes, readByteReaderU16, readByteReader
13
18
  // faces per layer, and volume images become depth slices. Video frames are rejected because the common
14
19
  // container descriptor cannot preserve their temporal/conditional-replenishment semantics truthfully.
15
20
  export function parseBasis(bytes) {
21
+ return parseBasisInternal(bytes);
22
+ }
23
+ function parseBasisInternal(bytes, failure) {
16
24
  if (!hasBasisSignature(bytes))
17
- return null;
25
+ return reject(failure, 'container-unrecognized');
18
26
  if (bytes.byteLength < basisHeaderMinSize)
19
- return null;
27
+ return reject(failure, 'header-truncated');
20
28
  const header = createByteReader(bytes, basisTotalSlicesOffset);
21
29
  const totalSlices = readByteReaderU24(header); // m_total_slices (offset 14)
22
30
  const totalImages = readByteReaderU24(header); // m_total_images (offset 17)
23
31
  const format = basisTexFormat[bytes[basisTexFormatOffset]]; // m_tex_format (offset 20)
24
32
  if (format === undefined)
25
- return null;
33
+ return reject(failure, 'format-unsupported');
26
34
  if (totalSlices === 0)
27
- return null;
35
+ return reject(failure, 'structure-invalid');
28
36
  const shape = getBasisTextureShape(bytes[basisTexTypeOffset], totalImages);
29
37
  if (shape === null)
30
- return null;
38
+ return reject(failure, 'format-unsupported');
31
39
  const sliceDescReader = createByteReader(bytes, basisSliceDescOffsetField);
32
40
  const sliceDescOffset = readByteReaderU32(sliceDescReader);
33
41
  const table = createByteReader(bytes, sliceDescOffset);
34
- if (!hasByteReaderBytes(table, totalSlices * basisSliceDescSize))
35
- return null;
42
+ if (!hasByteReaderBytes(table, totalSlices * basisSliceDescSize)) {
43
+ return reject(failure, 'level-range-out-of-bounds');
44
+ }
36
45
  const levels = [];
37
46
  let baseWidth = 0;
38
47
  let baseHeight = 0;
@@ -49,7 +58,7 @@ export function parseBasis(bytes) {
49
58
  const byteLength = readByteReaderU32(table);
50
59
  readByteReaderU16(table); // m_slice_data_crc16
51
60
  if (byteOffset + byteLength > bytes.byteLength)
52
- return null;
61
+ return reject(failure, 'level-range-out-of-bounds');
53
62
  if (imageIndex === 0 && levelIndex === 0) {
54
63
  baseWidth = width;
55
64
  baseHeight = height;
@@ -70,6 +79,11 @@ export function parseBasis(bytes) {
70
79
  width: baseWidth || (levels[0]?.width ?? 0),
71
80
  };
72
81
  }
82
+ function reject(failure, reason) {
83
+ if (failure !== undefined)
84
+ failure.reason = reason;
85
+ return null;
86
+ }
73
87
  function getBasisTextureShape(textureType, totalImages) {
74
88
  const images = Math.max(1, totalImages);
75
89
  switch (textureType) {
@@ -1 +1 @@
1
- {"version":3,"file":"parseBasis.js","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parseBasis.js","sourceRoot":"","sources":["../src/parseBasis.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
1
  import type { TextureContainer } from '@flighthq/types/contract';
2
+ import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
3
+ export declare function getDdsParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
2
4
  export declare function parseDds(bytes: Readonly<Uint8Array>): TextureContainer | null;
3
5
  //# sourceMappingURL=parseDds.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseDds.d.ts","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAiBjE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAsE7E"}
1
+ {"version":3,"file":"parseDds.d.ts","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAKnF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAI/G;AAaD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAE7E"}
package/dist/parseDds.js CHANGED
@@ -1,6 +1,11 @@
1
1
  import { createByteReader, hasByteReaderBytes, readByteReaderU32, skipByteReader } from './byteReader';
2
2
  import { computeTextureContainerLevels } from './textureLevelLayout';
3
- // Parses a DDS container (DirectDraw Surface) into a `TextureContainer`, or returns `null` if the bytes
3
+ export function getDdsParseFailureReason(bytes) {
4
+ const failure = { reason: null };
5
+ const container = parseDdsInternal(bytes, failure);
6
+ return container === null ? failure.reason : null;
7
+ }
8
+ // Parses a DDS container (DirectDraw Bitmap) into a `TextureContainer`, or returns `null` if the bytes
4
9
  // are not DDS, are truncated, or carry a pixel format this package does not map (e.g. a legacy 16/24-bit
5
10
  // layout, a YUV/luminance format, or a volume texture).
6
11
  //
@@ -12,10 +17,13 @@ import { computeTextureContainerLevels } from './textureLevelLayout';
12
17
  // `computeTextureContainerLevels`): sub-images are nested layer → face → mip, matching D3D subresource
13
18
  // order (a cubemap's 6 faces each hold a full mip chain).
14
19
  export function parseDds(bytes) {
20
+ return parseDdsInternal(bytes);
21
+ }
22
+ function parseDdsInternal(bytes, failure) {
15
23
  if (!hasDdsMagic(bytes))
16
- return null;
24
+ return reject(failure, 'container-unrecognized');
17
25
  if (bytes.byteLength < ddsDataOffset)
18
- return null;
26
+ return reject(failure, 'header-truncated');
19
27
  const reader = createByteReader(bytes, 4);
20
28
  skipByteReader(reader, 4); // dwSize
21
29
  skipByteReader(reader, 4); // dwFlags
@@ -34,15 +42,17 @@ export function parseDds(bytes) {
34
42
  const aMask = readByteReaderU32(reader);
35
43
  reader.offset = 112; // dwCaps2
36
44
  const caps2 = readByteReaderU32(reader);
37
- if ((caps2 & ddsCaps2Volume) !== 0 || dwDepth > 1)
38
- return null; // volume textures not modeled yet
45
+ if ((caps2 & ddsCaps2Volume) !== 0 || dwDepth > 1) {
46
+ return reject(failure, 'format-unsupported'); // volume textures not modeled yet
47
+ }
39
48
  let format;
40
49
  let cube = (caps2 & ddsCaps2Cubemap) !== 0;
41
50
  let layers = 1;
42
51
  let dataOffset = ddsDataOffset;
43
52
  if ((pfFlags & ddsPfFourCC) !== 0 && fourCC === ddsFourCcDx10) {
44
- if (!hasByteReaderBytes(createByteReader(bytes, ddsDataOffset), 20))
45
- return null;
53
+ if (!hasByteReaderBytes(createByteReader(bytes, ddsDataOffset), 20)) {
54
+ return reject(failure, 'header-truncated');
55
+ }
46
56
  const dx10 = createByteReader(bytes, ddsDataOffset);
47
57
  const dxgiFormat = readByteReaderU32(dx10);
48
58
  skipByteReader(dx10, 4); // resourceDimension
@@ -63,14 +73,15 @@ export function parseDds(bytes) {
63
73
  format = null;
64
74
  }
65
75
  if (format === null)
66
- return null;
76
+ return reject(failure, 'format-unsupported');
67
77
  const width = Math.max(1, dwWidth);
68
78
  const height = Math.max(1, dwHeight);
69
79
  const faces = cube ? 6 : 1;
70
80
  const mipLevels = Math.max(1, dwMipMapCount);
71
81
  const layout = computeTextureContainerLevels(format, width, height, mipLevels, layers, faces, dataOffset);
72
- if (layout === null || layout.endOffset > bytes.byteLength)
73
- return null;
82
+ if (layout === null || layout.endOffset > bytes.byteLength) {
83
+ return reject(failure, 'level-range-out-of-bounds');
84
+ }
74
85
  return {
75
86
  depth: 1,
76
87
  faces,
@@ -83,6 +94,11 @@ export function parseDds(bytes) {
83
94
  width,
84
95
  };
85
96
  }
97
+ function reject(failure, reason) {
98
+ if (failure !== undefined)
99
+ failure.reason = reason;
100
+ return null;
101
+ }
86
102
  function hasDdsMagic(bytes) {
87
103
  return bytes.byteLength >= 4 && bytes[0] === 0x44 && bytes[1] === 0x44 && bytes[2] === 0x53 && bytes[3] === 0x20;
88
104
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parseDds.js","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parseDds.js","sourceRoot":"","sources":["../src/parseDds.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACvG,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,UAAU,wBAAwB,CAAC,KAA2B;IAClE,MAAM,OAAO,GAAiB,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnD,OAAO,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAED,uGAAuG;AACvG,yGAAyG;AACzG,wDAAwD;AACxD,EAAE;AACF,kGAAkG;AAClG,2FAA2F;AAC3F,oGAAoG;AACpG,oGAAoG;AACpG,yFAAyF;AACzF,uGAAuG;AACvG,0DAA0D;AAC1D,MAAM,UAAU,QAAQ,CAAC,KAA2B;IAClD,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAA2B,EAAE,OAAsB;IAC3E,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;IAC1E,IAAI,KAAK,CAAC,UAAU,GAAG,aAAa;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;IAEjF,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1C,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;IACpC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU;IACrC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,sBAAsB;IACjD,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAEhD,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,0BAA0B;IAC9C,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAExC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU;IAC/B,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,kCAAkC;IAClF,CAAC;IAED,IAAI,MAAqC,CAAC;IAC1C,IAAI,IAAI,GAAG,CAAC,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,UAAU,GAAG,aAAa,CAAC;IAE/B,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC9D,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACpE,OAAO,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC3C,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,oBAAoB;QAC7C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;QAC3C,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAChC,UAAU,GAAG,aAAa,GAAG,EAAE,CAAC;IAClC,CAAC;SAAM,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAC3C,CAAC;SAAM,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,GAAG,kBAAkB,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAElE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,6BAA6B,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAC1G,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;QAC3D,OAAO,MAAM,CAAC,OAAO,EAAE,2BAA2B,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC;QACR,KAAK;QACL,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS;QACT,gBAAgB,EAAE,MAAM;QACxB,KAAK;KACN,CAAC;AACJ,CAAC;AAMD,SAAS,MAAM,CAAC,OAAiC,EAAE,MAA0C;IAC3F,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,KAA2B;IAC9C,OAAO,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AACnH,CAAC;AAED,SAAS,kBAAkB,CACzB,WAAmB,EACnB,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa;IAEb,IAAI,WAAW,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACjG,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACjG,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wFAAwF;AACxF,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,SAAS;AAC5C,MAAM,WAAW,GAAG,GAAG,CAAC;AACxB,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB,qGAAqG;AACrG,mEAAmE;AACnE,MAAM,aAAa,GAAqD;IACtE,CAAC,EAAE,SAAS;IACZ,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,WAAW;IACf,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,YAAY;IAChB,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,SAAS;CACd,CAAC;AAEF,kGAAkG;AAClG,qGAAqG;AACrG,MAAM,eAAe,GAAqD;IACxE,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,UAAU,EAAE,OAAO;IAChC,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,KAAK,EAAE,OAAO;IAC3B,WAAW,EAAE,UAAU,EAAE,OAAO;CACjC,CAAC"}
@@ -1,3 +1,5 @@
1
1
  import type { TextureContainer } from '@flighthq/types/contract';
2
+ import type { TextureContainerParseFailureReason } from '@flighthq/types/contract';
3
+ export declare function getKtx2ParseFailureReason(bytes: Readonly<Uint8Array>): TextureContainerParseFailureReason | null;
2
4
  export declare function parseKtx2(bytes: Readonly<Uint8Array>): TextureContainer | null;
3
5
  //# sourceMappingURL=parseKtx2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseKtx2.d.ts","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAyBjE,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAsF9E"}
1
+ {"version":3,"file":"parseKtx2.d.ts","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAWnF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,kCAAkC,GAAG,IAAI,CAIhH;AAcD,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAE9E"}
package/dist/parseKtx2.js CHANGED
@@ -1,4 +1,9 @@
1
1
  import { createByteReader, hasByteReaderBytes, readByteReaderU32, readByteReaderU64, skipByteReader, } from './byteReader';
2
+ export function getKtx2ParseFailureReason(bytes) {
3
+ const failure = { reason: null };
4
+ const container = parseKtx2Internal(bytes, failure);
5
+ return container === null ? failure.reason : null;
6
+ }
2
7
  // Parses a KTX2 container (Khronos KTX 2.0) into a `TextureContainer`, or returns `null` if the bytes
3
8
  // are not KTX2, are truncated, or carry a `vkFormat`/supercompression this package does not map yet.
4
9
  //
@@ -12,11 +17,14 @@ import { createByteReader, hasByteReaderBytes, readByteReaderU32, readByteReader
12
17
  // sub-images and normalized from KTX2's mip-major file order into TextureContainer's canonical
13
18
  // layer → face → mip order.
14
19
  export function parseKtx2(bytes) {
20
+ return parseKtx2Internal(bytes);
21
+ }
22
+ function parseKtx2Internal(bytes, failure) {
15
23
  if (!hasKtx2Identifier(bytes))
16
- return null;
24
+ return reject(failure, 'container-unrecognized');
17
25
  // 12 id + 68 header/index (17 u32 = 68 bytes) before the level index at offset 80.
18
26
  if (bytes.byteLength < ktx2LevelIndexOffset)
19
- return null;
27
+ return reject(failure, 'header-truncated');
20
28
  const reader = createByteReader(bytes, 12);
21
29
  const vkFormat = readByteReaderU32(reader);
22
30
  skipByteReader(reader, 4); // typeSize
@@ -30,10 +38,10 @@ export function parseKtx2(bytes) {
30
38
  // dfd/kvd/sgd index (2 u32 + 2 u32 + 2 u64 = 32 bytes) — not needed to locate levels.
31
39
  const supercompression = ktx2Supercompression[supercompressionScheme];
32
40
  if (supercompression === undefined)
33
- return null;
41
+ return reject(failure, 'format-unsupported');
34
42
  const format = mapKtx2Format(vkFormat, supercompressionScheme);
35
43
  if (format === null)
36
- return null;
44
+ return reject(failure, 'format-unsupported');
37
45
  const width = Math.max(1, pixelWidth);
38
46
  const height = Math.max(1, pixelHeight);
39
47
  const depth = Math.max(1, pixelDepth);
@@ -42,7 +50,7 @@ export function parseKtx2(bytes) {
42
50
  const levelCountPresent = Math.max(1, levelCount);
43
51
  reader.offset = ktx2LevelIndexOffset;
44
52
  if (!hasByteReaderBytes(reader, levelCountPresent * 24))
45
- return null;
53
+ return reject(failure, 'level-range-out-of-bounds');
46
54
  const fileOrderLevels = [];
47
55
  const imagesPerLevel = layers * faces;
48
56
  for (let mip = 0; mip < levelCountPresent; mip += 1) {
@@ -50,7 +58,7 @@ export function parseKtx2(bytes) {
50
58
  const byteLength = readByteReaderU64(reader);
51
59
  skipByteReader(reader, 8); // uncompressedByteLength
52
60
  if (byteOffset + byteLength > bytes.byteLength)
53
- return null;
61
+ return reject(failure, 'level-range-out-of-bounds');
54
62
  const mipWidth = Math.max(1, width >> mip);
55
63
  const mipHeight = Math.max(1, height >> mip);
56
64
  const splittable = supercompression === 'None' && imagesPerLevel > 1 && byteLength % imagesPerLevel === 0;
@@ -91,6 +99,11 @@ export function parseKtx2(bytes) {
91
99
  width,
92
100
  };
93
101
  }
102
+ function reject(failure, reason) {
103
+ if (failure !== undefined)
104
+ failure.reason = reason;
105
+ return null;
106
+ }
94
107
  function hasKtx2Identifier(bytes) {
95
108
  if (bytes.byteLength < 12)
96
109
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"parseKtx2.js","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parseKtx2.js","sourceRoot":"","sources":["../src/parseKtx2.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "name": "@flighthq/texture-formats",
3
- "version": "0.3.0-next.906.07cea63",
3
+ "version": "0.3.0",
4
+ "author": "Joshua Granick and other contributors",
5
+ "license": "MIT",
4
6
  "repository": {
5
7
  "type": "git",
6
8
  "url": "https://github.com/flighthq/flight.git",
@@ -36,7 +38,7 @@
36
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
37
39
  },
38
40
  "dependencies": {
39
- "@flighthq/types": "0.3.0-next.906.07cea63"
41
+ "@flighthq/types": "0.3.0"
40
42
  },
41
43
  "devDependencies": {
42
44
  "typescript": "^5.3.0"
@@ -0,0 +1,65 @@
1
+ import { explainTextureContainerParse } from './explainTextureContainerParse';
2
+
3
+ describe('explainTextureContainerParse', () => {
4
+ it('reports an unrecognized container', () => {
5
+ expect(explainTextureContainerParse(new Uint8Array([0, 1, 2, 3]))).toEqual({
6
+ container: null,
7
+ reason: 'container-unrecognized',
8
+ });
9
+ });
10
+
11
+ it.each([
12
+ ['atf', new Uint8Array([0x41, 0x54, 0x46])],
13
+ ['basis', new Uint8Array([0x73, 0x42])],
14
+ ['dds', new Uint8Array([0x44, 0x44, 0x53, 0x20])],
15
+ ['ktx2', new Uint8Array(ktx2Identifier)],
16
+ ] as const)('reports a truncated %s header', (container, bytes) => {
17
+ expect(explainTextureContainerParse(bytes)).toEqual({ container, reason: 'header-truncated' });
18
+ });
19
+
20
+ it('distinguishes unsupported formats from invalid structures', () => {
21
+ expect(explainTextureContainerParse(createKtx2({ vkFormat: 999 }))).toEqual({
22
+ container: 'ktx2',
23
+ reason: 'format-unsupported',
24
+ });
25
+
26
+ const basis = new Uint8Array(67);
27
+ basis.set([0x73, 0x42]);
28
+ expect(explainTextureContainerParse(basis)).toEqual({
29
+ container: 'basis',
30
+ reason: 'structure-invalid',
31
+ });
32
+ });
33
+
34
+ it('reports a level range that overruns the bytes', () => {
35
+ expect(explainTextureContainerParse(createKtx2({ byteLength: 8 }))).toEqual({
36
+ container: 'ktx2',
37
+ reason: 'level-range-out-of-bounds',
38
+ });
39
+ });
40
+
41
+ it('returns null when the detected container parses', () => {
42
+ expect(explainTextureContainerParse(createKtx2({ byteLength: 1, payloadBytes: 1 }))).toBeNull();
43
+ });
44
+ });
45
+
46
+ function createKtx2(options: {
47
+ readonly byteLength?: number;
48
+ readonly payloadBytes?: number;
49
+ readonly vkFormat?: number;
50
+ }) {
51
+ const bytes = new Uint8Array(104 + (options.payloadBytes ?? 0));
52
+ bytes.set(ktx2Identifier);
53
+ const view = new DataView(bytes.buffer);
54
+ view.setUint32(12, options.vkFormat ?? 37, true);
55
+ view.setUint32(20, 1, true); // pixelWidth
56
+ view.setUint32(24, 1, true); // pixelHeight
57
+ view.setUint32(36, 1, true); // faceCount
58
+ view.setUint32(40, 1, true); // levelCount
59
+ view.setUint32(80, 104, true); // level byteOffset, low u32 of u64
60
+ view.setUint32(88, options.byteLength ?? 0, true); // level byteLength, low u32 of u64
61
+ view.setUint32(96, options.byteLength ?? 0, true); // uncompressedByteLength, low u32 of u64
62
+ return bytes;
63
+ }
64
+
65
+ const ktx2Identifier: readonly number[] = [0xab, 0x4b, 0x54, 0x58, 0x20, 0x32, 0x30, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a];
@@ -1,7 +1,7 @@
1
1
  import type { TextureContainer } from '@flighthq/types/contract';
2
2
  import { describe, expect, it } from 'vitest';
3
3
 
4
- import { parseAtf } from './parseAtf';
4
+ import { getAtfParseFailureReason, parseAtf } from './parseAtf';
5
5
  import { selectTextureContainer } from './selectTextureContainer';
6
6
 
7
7
  interface AtfOptions {
@@ -80,6 +80,12 @@ function expectLevelRangesInBounds(containers: readonly TextureContainer[], byte
80
80
  }
81
81
  }
82
82
 
83
+ describe('getAtfParseFailureReason', () => {
84
+ it('reports a truncated detected header', () => {
85
+ expect(getAtfParseFailureReason(new Uint8Array([0x41, 0x54, 0x46]))).toBe('header-truncated');
86
+ });
87
+ });
88
+
83
89
  describe('parseAtf', () => {
84
90
  it('parses a cross-platform ATF as one peer container per populated GPU-format slot', () => {
85
91
  // Version 3, format 5 (RAW_COMPRESSED_ALPHA), 8x8, 3 mips, all four slots populated.
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
- import { parseBasis } from './parseBasis';
3
+ import { getBasisParseFailureReason, parseBasis } from './parseBasis';
4
4
 
5
5
  interface BasisSlice {
6
6
  imageIndex: number;
@@ -54,6 +54,12 @@ function buildBasis(opts: BasisOptions): Uint8Array {
54
54
  return bytes;
55
55
  }
56
56
 
57
+ describe('getBasisParseFailureReason', () => {
58
+ it('reports a truncated detected header', () => {
59
+ expect(getBasisParseFailureReason(new Uint8Array([0x73, 0x42]))).toBe('header-truncated');
60
+ });
61
+ });
62
+
57
63
  describe('parseBasis', () => {
58
64
  it('parses a single-slice ETC1S image', () => {
59
65
  const container = parseBasis(
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
- import { parseDds } from './parseDds';
3
+ import { getDdsParseFailureReason, parseDds } from './parseDds';
4
4
 
5
5
  function fourCC(text: string): number {
6
6
  return (
@@ -66,6 +66,12 @@ function buildDds(opts: DdsOptions): Uint8Array {
66
66
  return bytes;
67
67
  }
68
68
 
69
+ describe('getDdsParseFailureReason', () => {
70
+ it('reports a truncated detected header', () => {
71
+ expect(getDdsParseFailureReason(new Uint8Array([0x44, 0x44, 0x53, 0x20]))).toBe('header-truncated');
72
+ });
73
+ });
74
+
69
75
  describe('parseDds', () => {
70
76
  it('parses a single-mip BC1 (DXT1) texture', () => {
71
77
  const container = parseDds(buildDds({ fourCC: fourCC('DXT1'), height: 4, pfFlags: 0x4, width: 4 }));
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
- import { parseKtx2 } from './parseKtx2';
3
+ import { getKtx2ParseFailureReason, parseKtx2 } from './parseKtx2';
4
4
 
5
5
  const ktx2Magic = [0xab, 0x4b, 0x54, 0x58, 0x20, 0x32, 0x30, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a];
6
6
 
@@ -46,6 +46,12 @@ function buildKtx2(opts: Ktx2Options): Uint8Array {
46
46
  return bytes;
47
47
  }
48
48
 
49
+ describe('getKtx2ParseFailureReason', () => {
50
+ it('reports a truncated detected header', () => {
51
+ expect(getKtx2ParseFailureReason(new Uint8Array(ktx2Magic))).toBe('header-truncated');
52
+ });
53
+ });
54
+
49
55
  describe('parseKtx2', () => {
50
56
  it('parses a single-mip uncompressed 2D texture', () => {
51
57
  const container = parseKtx2(