wpd-codec 3.5.0 → 3.5.2

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 (39) hide show
  1. package/dist/container/container.cjs +2 -3
  2. package/dist/container/container.js +2 -3
  3. package/dist/container/encryption.cjs +7 -3
  4. package/dist/container/encryption.d.cts +2 -1
  5. package/dist/container/encryption.d.ts +2 -1
  6. package/dist/container/encryption.js +7 -4
  7. package/dist/container/header.cjs +0 -1
  8. package/dist/container/header.js +0 -1
  9. package/dist/container/prefix.cjs +19 -16
  10. package/dist/container/prefix.js +19 -16
  11. package/dist/container/summary.cjs +10 -4
  12. package/dist/container/summary.js +10 -4
  13. package/dist/read.cjs +10 -17
  14. package/dist/read.d.cts +3 -1
  15. package/dist/read.d.ts +3 -1
  16. package/dist/read.js +9 -18
  17. package/dist/stream/box.cjs +61 -70
  18. package/dist/stream/box.js +61 -70
  19. package/dist/stream/characters.cjs +2 -0
  20. package/dist/stream/characters.d.cts +2 -1
  21. package/dist/stream/characters.d.ts +2 -1
  22. package/dist/stream/characters.js +2 -1
  23. package/dist/stream/formula.cjs +14 -16
  24. package/dist/stream/formula.js +15 -17
  25. package/dist/stream/image.cjs +55 -41
  26. package/dist/stream/image.d.cts +3 -1
  27. package/dist/stream/image.d.ts +3 -1
  28. package/dist/stream/image.js +55 -43
  29. package/dist/stream/ole.cjs +1 -1
  30. package/dist/stream/ole.js +2 -2
  31. package/dist/stream/style.cjs +15 -13
  32. package/dist/stream/style.js +15 -13
  33. package/dist/stream/table.cjs +47 -33
  34. package/dist/stream/table.d.cts +3 -2
  35. package/dist/stream/table.d.ts +3 -2
  36. package/dist/stream/table.js +48 -35
  37. package/dist/stream/wpg.cjs +38 -40
  38. package/dist/stream/wpg.js +38 -40
  39. package/package.json +4 -4
@@ -7,83 +7,74 @@ const OVERRIDE_BIT_HTML = 7;
7
7
  const OVERRIDE_FLAGS_OFFSET = 18;
8
8
  const FIRST_OVERRIDE_BLOCK_OFFSET = 20;
9
9
  function walkOverrideBlocks(nonDeletable) {
10
- if (nonDeletable.length < FIRST_OVERRIDE_BLOCK_OFFSET) return;
11
- const flags = uint16At(nonDeletable, OVERRIDE_FLAGS_OFFSET);
12
- const blocks = /* @__PURE__ */ new Map();
13
- let cursor = FIRST_OVERRIDE_BLOCK_OFFSET;
14
- for (let bit = 15; bit >= 5; bit -= 1) {
15
- if ((flags & 1 << bit) === 0) continue;
16
- if (bit === OVERRIDE_BIT_HTML) continue;
17
- if (cursor + 2 > nonDeletable.length) return;
18
- const size = uint16At(nonDeletable, cursor);
19
- cursor += 2;
20
- if (cursor + size > nonDeletable.length) return;
21
- blocks.set(bit, nonDeletable.subarray(cursor, cursor + size));
22
- cursor += size;
10
+ try {
11
+ const flags = uint16At(nonDeletable, OVERRIDE_FLAGS_OFFSET);
12
+ const blocks = /* @__PURE__ */ new Map();
13
+ let cursor = FIRST_OVERRIDE_BLOCK_OFFSET;
14
+ for (let bit = 15; bit >= 5; bit -= 1) {
15
+ if ((flags & 1 << bit) === 0) continue;
16
+ if (bit === OVERRIDE_BIT_HTML) continue;
17
+ const size = uint16At(nonDeletable, cursor);
18
+ cursor += 2;
19
+ if (cursor + size > nonDeletable.length) return;
20
+ blocks.set(bit, nonDeletable.subarray(cursor, cursor + size));
21
+ cursor += size;
22
+ }
23
+ return {
24
+ flags,
25
+ blocks
26
+ };
27
+ } catch {
28
+ return;
23
29
  }
24
- return {
25
- flags,
26
- blocks
27
- };
28
30
  }
29
31
  function readContentType(contentBlock) {
30
- if (contentBlock.length < 2) return;
31
- const flags = uint16At(contentBlock, 0);
32
- let cursor = 2;
33
- if ((flags & 32768) !== 0) {
34
- if (cursor + 2 > contentBlock.length) return;
35
- cursor += 2;
32
+ try {
33
+ const flags = uint16At(contentBlock, 0);
34
+ let cursor = 2;
35
+ if ((flags & 32768) !== 0) cursor += 2;
36
+ if ((flags & 16384) === 0) return;
37
+ return contentBlock[cursor];
38
+ } catch {
39
+ return;
36
40
  }
37
- if ((flags & 16384) === 0) return;
38
- return contentBlock[cursor];
39
41
  }
40
42
  function readPositionOverride(positionBlock) {
41
- if (positionBlock.length < 2) return;
42
- const flags = uint16At(positionBlock, 0);
43
- let cursor = 2;
44
- let widthWpu;
45
- let heightWpu;
46
- let xWpu;
47
- let yWpu;
48
- const need = (bytes) => cursor + bytes <= positionBlock.length;
49
- if ((flags & 32768) !== 0) {
50
- if (!need(2)) return void 0;
51
- cursor += 2;
52
- }
53
- if ((flags & 16384) !== 0) {
54
- if (!need(2)) return void 0;
55
- cursor += 2;
56
- }
57
- if ((flags & 8192) !== 0) {
58
- if (!need(5)) return void 0;
59
- const horizontalFlags = positionBlock[cursor];
60
- const offset = uint16At(positionBlock, cursor + 1);
61
- if (horizontalFlags !== void 0 && (horizontalFlags & 3) === 0) xWpu = offset;
62
- cursor += 5;
63
- }
64
- if ((flags & 4096) !== 0) {
65
- if (!need(3)) return void 0;
66
- const verticalFlags = positionBlock[cursor];
67
- const offset = uint16At(positionBlock, cursor + 1);
68
- if (verticalFlags !== void 0 && (verticalFlags & 3) === 0) yWpu = offset;
69
- cursor += 3;
70
- }
71
- if ((flags & 2048) !== 0) {
72
- if (!need(3)) return void 0;
73
- widthWpu = uint16At(positionBlock, cursor + 1);
74
- cursor += 3;
75
- }
76
- if ((flags & 1024) !== 0) {
77
- if (!need(3)) return void 0;
78
- heightWpu = uint16At(positionBlock, cursor + 1);
79
- cursor += 3;
43
+ try {
44
+ const flags = uint16At(positionBlock, 0);
45
+ let cursor = 2;
46
+ let widthWpu;
47
+ let heightWpu;
48
+ let xWpu;
49
+ let yWpu;
50
+ if ((flags & 32768) !== 0) cursor += 2;
51
+ if ((flags & 16384) !== 0) cursor += 2;
52
+ if ((flags & 8192) !== 0) {
53
+ const horizontalFlags = positionBlock[cursor];
54
+ const offset = uint16At(positionBlock, cursor + 1);
55
+ if (horizontalFlags !== void 0 && (horizontalFlags & 3) === 0) xWpu = offset;
56
+ cursor += 5;
57
+ }
58
+ if ((flags & 4096) !== 0) {
59
+ const verticalFlags = positionBlock[cursor];
60
+ const offset = uint16At(positionBlock, cursor + 1);
61
+ if (verticalFlags !== void 0 && (verticalFlags & 3) === 0) yWpu = offset;
62
+ cursor += 3;
63
+ }
64
+ if ((flags & 2048) !== 0) {
65
+ widthWpu = uint16At(positionBlock, cursor + 1);
66
+ cursor += 3;
67
+ }
68
+ if ((flags & 1024) !== 0) heightWpu = uint16At(positionBlock, cursor + 1);
69
+ return {
70
+ widthWpu,
71
+ heightWpu,
72
+ xWpu,
73
+ yWpu
74
+ };
75
+ } catch {
76
+ return;
80
77
  }
81
- return {
82
- widthWpu,
83
- heightWpu,
84
- xWpu,
85
- yWpu
86
- };
87
78
  }
88
79
  const BOX_CONTENT_TYPE_TEXT = 1;
89
80
  const BOX_CONTENT_TYPE_LINKED_TEXT = 2;
@@ -179,6 +179,7 @@ function decodeSingleByteCharacter(byte) {
179
179
  if (shorthand !== void 0) return shorthand;
180
180
  if (byte >= 33 && byte <= 127) return String.fromCharCode(byte);
181
181
  }
182
+ const UNBOUNDED_WORDS = Number.POSITIVE_INFINITY;
182
183
  function decodeWordString(bytes, offset, maxWords) {
183
184
  let text = "";
184
185
  let wordsRead = 0;
@@ -198,6 +199,7 @@ function decodeWordString(bytes, offset, maxWords) {
198
199
  //#endregion
199
200
  exports.FIRST_ASCII_CHARACTER = FIRST_ASCII_CHARACTER;
200
201
  exports.LAST_CHARACTER = LAST_CHARACTER;
202
+ exports.UNBOUNDED_WORDS = UNBOUNDED_WORDS;
201
203
  exports.UNMAPPED_CHARACTER = UNMAPPED_CHARACTER;
202
204
  exports.decodeSingleByteCharacter = decodeSingleByteCharacter;
203
205
  exports.decodeWordString = decodeWordString;
@@ -4,9 +4,10 @@ declare const LAST_CHARACTER = 127;
4
4
  declare const UNMAPPED_CHARACTER = "�";
5
5
  declare function decodeWpCharacter(characterSet: number, characterNumber: number): string | undefined;
6
6
  declare function decodeSingleByteCharacter(byte: number): string | undefined;
7
+ declare const UNBOUNDED_WORDS: number;
7
8
  declare function decodeWordString(bytes: Uint8Array, offset: number, maxWords: number): {
8
9
  text: string;
9
10
  wordsRead: number;
10
11
  };
11
12
  //#endregion
12
- export { FIRST_ASCII_CHARACTER, LAST_CHARACTER, UNMAPPED_CHARACTER, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter };
13
+ export { FIRST_ASCII_CHARACTER, LAST_CHARACTER, UNBOUNDED_WORDS, UNMAPPED_CHARACTER, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter };
@@ -4,9 +4,10 @@ declare const LAST_CHARACTER = 127;
4
4
  declare const UNMAPPED_CHARACTER = "�";
5
5
  declare function decodeWpCharacter(characterSet: number, characterNumber: number): string | undefined;
6
6
  declare function decodeSingleByteCharacter(byte: number): string | undefined;
7
+ declare const UNBOUNDED_WORDS: number;
7
8
  declare function decodeWordString(bytes: Uint8Array, offset: number, maxWords: number): {
8
9
  text: string;
9
10
  wordsRead: number;
10
11
  };
11
12
  //#endregion
12
- export { FIRST_ASCII_CHARACTER, LAST_CHARACTER, UNMAPPED_CHARACTER, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter };
13
+ export { FIRST_ASCII_CHARACTER, LAST_CHARACTER, UNBOUNDED_WORDS, UNMAPPED_CHARACTER, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter };
@@ -178,6 +178,7 @@ function decodeSingleByteCharacter(byte) {
178
178
  if (shorthand !== void 0) return shorthand;
179
179
  if (byte >= 33 && byte <= 127) return String.fromCharCode(byte);
180
180
  }
181
+ const UNBOUNDED_WORDS = Number.POSITIVE_INFINITY;
181
182
  function decodeWordString(bytes, offset, maxWords) {
182
183
  let text = "";
183
184
  let wordsRead = 0;
@@ -195,4 +196,4 @@ function decodeWordString(bytes, offset, maxWords) {
195
196
  };
196
197
  }
197
198
  //#endregion
198
- export { FIRST_ASCII_CHARACTER, LAST_CHARACTER, UNMAPPED_CHARACTER, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter };
199
+ export { FIRST_ASCII_CHARACTER, LAST_CHARACTER, UNBOUNDED_WORDS, UNMAPPED_CHARACTER, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter };
@@ -163,14 +163,11 @@ function readLengthPrefixedWordString(cursor) {
163
163
  cursor.offset += length * 2;
164
164
  return text;
165
165
  }
166
- function readLengthPrefixedByteString(cursor) {
167
- if (cursor.offset + 2 > cursor.bytes.length) return;
168
- const length = require_bytes_view.uint16At(cursor.bytes, cursor.offset);
166
+ function skipLengthPrefixedByteString(cursor) {
167
+ const length = require_bytes_view.uint16At(require_bytes_view.sliceAt(cursor.bytes, cursor.offset, 2), 0);
169
168
  cursor.offset += 2;
170
- if (cursor.offset + length > cursor.bytes.length) return;
171
- const slice = cursor.bytes.subarray(cursor.offset, cursor.offset + length);
169
+ require_bytes_view.sliceAt(cursor.bytes, cursor.offset, length);
172
170
  cursor.offset += length;
173
- return Array.from(slice, (byte) => String.fromCharCode(byte)).join("");
174
171
  }
175
172
  function readCellNumber(cursor) {
176
173
  if (cursor.offset + 4 > cursor.bytes.length) return;
@@ -224,17 +221,20 @@ function readToken(cursor) {
224
221
  }
225
222
  case 28: {
226
223
  const start = readCellNumber(cursor);
227
- const end = start === void 0 ? void 0 : readCellNumber(cursor);
224
+ const end = readCellNumber(cursor);
228
225
  if (start === void 0 || end === void 0) return;
229
226
  const startText = cellReferenceText(start.row, start.column, false, false);
230
227
  const endText = cellReferenceText(end.row, end.column, false, false);
231
228
  return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
232
229
  }
233
- case 30: {
234
- if (cursor.offset + 8 > cursor.bytes.length) return;
235
- const value = new DataView(cursor.bytes.buffer, cursor.bytes.byteOffset + cursor.offset, 8).getFloat64(0, true);
230
+ case 30: try {
231
+ const doubleBytes = require_bytes_view.sliceAt(cursor.bytes, cursor.offset, 8);
232
+ const value = new DataView(doubleBytes.buffer, doubleBytes.byteOffset, 8).getFloat64(0, true);
236
233
  cursor.offset += 8;
237
- return readLengthPrefixedByteString(cursor) === void 0 ? void 0 : String(value);
234
+ skipLengthPrefixedByteString(cursor);
235
+ return String(value);
236
+ } catch {
237
+ return;
238
238
  }
239
239
  case 31: {
240
240
  if (cursor.offset + 2 > cursor.bytes.length) return;
@@ -245,24 +245,22 @@ function readToken(cursor) {
245
245
  case 32: return readLengthPrefixedWordString(cursor);
246
246
  case 41:
247
247
  case 42:
248
- cursor.offset += 2;
249
- return "";
250
248
  case 43:
251
249
  cursor.offset += 2;
252
250
  return "";
253
251
  case 44: return "";
254
252
  default:
255
253
  if (code >= 48 && code <= 63) {
256
- const flags = code - 48;
254
+ const flags = code & 15;
257
255
  const start = readCellNumber(cursor);
258
- const end = start === void 0 ? void 0 : readCellNumber(cursor);
256
+ const end = readCellNumber(cursor);
259
257
  if (start === void 0 || end === void 0) return;
260
258
  const startText = cellReferenceText(start.row, start.column, (flags & 4) !== 0, (flags & 8) !== 0);
261
259
  const endText = cellReferenceText(end.row, end.column, (flags & 1) !== 0, (flags & 2) !== 0);
262
260
  return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
263
261
  }
264
262
  if (code >= 64 && code <= 67) {
265
- const flags = code - 64;
263
+ const flags = code & 3;
266
264
  const cell = readCellNumber(cursor);
267
265
  return cell === void 0 ? void 0 : cellReferenceText(cell.row, cell.column, (flags & 1) !== 0, (flags & 2) !== 0);
268
266
  }
@@ -1,4 +1,4 @@
1
- import { int16At, uint16At } from "../bytes/view.js";
1
+ import { int16At, sliceAt, uint16At } from "../bytes/view.js";
2
2
  import { decodeWordString } from "./characters.js";
3
3
  //#region src/stream/formula.ts
4
4
  const GROUP1_FUNCTIONS = /* @__PURE__ */ new Map([
@@ -162,14 +162,11 @@ function readLengthPrefixedWordString(cursor) {
162
162
  cursor.offset += length * 2;
163
163
  return text;
164
164
  }
165
- function readLengthPrefixedByteString(cursor) {
166
- if (cursor.offset + 2 > cursor.bytes.length) return;
167
- const length = uint16At(cursor.bytes, cursor.offset);
165
+ function skipLengthPrefixedByteString(cursor) {
166
+ const length = uint16At(sliceAt(cursor.bytes, cursor.offset, 2), 0);
168
167
  cursor.offset += 2;
169
- if (cursor.offset + length > cursor.bytes.length) return;
170
- const slice = cursor.bytes.subarray(cursor.offset, cursor.offset + length);
168
+ sliceAt(cursor.bytes, cursor.offset, length);
171
169
  cursor.offset += length;
172
- return Array.from(slice, (byte) => String.fromCharCode(byte)).join("");
173
170
  }
174
171
  function readCellNumber(cursor) {
175
172
  if (cursor.offset + 4 > cursor.bytes.length) return;
@@ -223,17 +220,20 @@ function readToken(cursor) {
223
220
  }
224
221
  case 28: {
225
222
  const start = readCellNumber(cursor);
226
- const end = start === void 0 ? void 0 : readCellNumber(cursor);
223
+ const end = readCellNumber(cursor);
227
224
  if (start === void 0 || end === void 0) return;
228
225
  const startText = cellReferenceText(start.row, start.column, false, false);
229
226
  const endText = cellReferenceText(end.row, end.column, false, false);
230
227
  return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
231
228
  }
232
- case 30: {
233
- if (cursor.offset + 8 > cursor.bytes.length) return;
234
- const value = new DataView(cursor.bytes.buffer, cursor.bytes.byteOffset + cursor.offset, 8).getFloat64(0, true);
229
+ case 30: try {
230
+ const doubleBytes = sliceAt(cursor.bytes, cursor.offset, 8);
231
+ const value = new DataView(doubleBytes.buffer, doubleBytes.byteOffset, 8).getFloat64(0, true);
235
232
  cursor.offset += 8;
236
- return readLengthPrefixedByteString(cursor) === void 0 ? void 0 : String(value);
233
+ skipLengthPrefixedByteString(cursor);
234
+ return String(value);
235
+ } catch {
236
+ return;
237
237
  }
238
238
  case 31: {
239
239
  if (cursor.offset + 2 > cursor.bytes.length) return;
@@ -244,24 +244,22 @@ function readToken(cursor) {
244
244
  case 32: return readLengthPrefixedWordString(cursor);
245
245
  case 41:
246
246
  case 42:
247
- cursor.offset += 2;
248
- return "";
249
247
  case 43:
250
248
  cursor.offset += 2;
251
249
  return "";
252
250
  case 44: return "";
253
251
  default:
254
252
  if (code >= 48 && code <= 63) {
255
- const flags = code - 48;
253
+ const flags = code & 15;
256
254
  const start = readCellNumber(cursor);
257
- const end = start === void 0 ? void 0 : readCellNumber(cursor);
255
+ const end = readCellNumber(cursor);
258
256
  if (start === void 0 || end === void 0) return;
259
257
  const startText = cellReferenceText(start.row, start.column, (flags & 4) !== 0, (flags & 8) !== 0);
260
258
  const endText = cellReferenceText(end.row, end.column, (flags & 1) !== 0, (flags & 2) !== 0);
261
259
  return startText === void 0 || endText === void 0 ? void 0 : `${startText}:${endText}`;
262
260
  }
263
261
  if (code >= 64 && code <= 67) {
264
- const flags = code - 64;
262
+ const flags = code & 3;
265
263
  const cell = readCellNumber(cursor);
266
264
  return cell === void 0 ? void 0 : cellReferenceText(cell.row, cell.column, (flags & 1) !== 0, (flags & 2) !== 0);
267
265
  }
@@ -12,61 +12,75 @@ const PNG_SIGNATURE = [
12
12
  10
13
13
  ];
14
14
  const JPEG_SOI = [255, 216];
15
+ function bytesMatchAt(bytes, index, signature) {
16
+ return signature.every((byte, offset) => require_bytes_view.byteAt(bytes, index + offset) === byte);
17
+ }
15
18
  function indexOf(bytes, needle, from) {
16
- outer: for (let i = from; i + needle.length <= bytes.length; i += 1) {
17
- for (let j = 0; j < needle.length; j += 1) if (bytes[i + j] !== needle[j]) continue outer;
18
- return i;
19
- }
19
+ for (let index = from;; index += 1) if (bytesMatchAt(bytes, index, needle)) return index;
20
+ }
21
+ function bigEndianUint32At(bytes, offset) {
22
+ return require_bytes_view.byteAt(bytes, offset) * 16777216 + require_bytes_view.byteAt(bytes, offset + 1) * 65536 + require_bytes_view.byteAt(bytes, offset + 2) * 256 + require_bytes_view.byteAt(bytes, offset + 3);
23
+ }
24
+ function bigEndianUint16At(bytes, offset) {
25
+ return require_bytes_view.byteAt(bytes, offset) * 256 + require_bytes_view.byteAt(bytes, offset + 1);
20
26
  }
21
27
  function scanPng(bytes, signatureAt) {
22
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
23
28
  let cursor = signatureAt + PNG_SIGNATURE.length;
24
- for (;;) {
25
- if (cursor + 8 > bytes.length) return;
26
- const length = view.getUint32(cursor);
27
- const type = String.fromCharCode(require_bytes_view.byteAt(bytes, cursor + 4), require_bytes_view.byteAt(bytes, cursor + 5), require_bytes_view.byteAt(bytes, cursor + 6), require_bytes_view.byteAt(bytes, cursor + 7));
28
- cursor += 8 + length + 4;
29
- if (cursor > bytes.length) return;
30
- if (type === "IEND") return {
31
- format: "png",
32
- bytes: bytes.subarray(signatureAt, cursor)
33
- };
29
+ try {
30
+ for (;;) {
31
+ const length = bigEndianUint32At(bytes, cursor);
32
+ const type = String.fromCharCode(require_bytes_view.byteAt(bytes, cursor + 4), require_bytes_view.byteAt(bytes, cursor + 5), require_bytes_view.byteAt(bytes, cursor + 6), require_bytes_view.byteAt(bytes, cursor + 7));
33
+ cursor += 8 + length + 4;
34
+ if (type === "IEND") return {
35
+ format: "png",
36
+ bytes: require_bytes_view.sliceAt(bytes, signatureAt, cursor - signatureAt)
37
+ };
38
+ }
39
+ } catch {
40
+ return;
34
41
  }
35
42
  }
36
43
  function scanJpeg(bytes, soiAt) {
37
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
38
44
  let cursor = soiAt + JPEG_SOI.length;
39
- for (;;) {
40
- if (cursor >= bytes.length) return;
41
- if (require_bytes_view.byteAt(bytes, cursor) !== 255) return;
42
- while (cursor < bytes.length && require_bytes_view.byteAt(bytes, cursor) === 255) cursor += 1;
43
- if (cursor >= bytes.length) return;
44
- const marker = require_bytes_view.byteAt(bytes, cursor);
45
- cursor += 1;
46
- if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) continue;
47
- if (marker === 217) return {
48
- format: "jpeg",
49
- bytes: bytes.subarray(soiAt, cursor)
50
- };
51
- if (cursor + 2 > bytes.length) return;
52
- const length = view.getUint16(cursor);
53
- if (length < 2 || cursor + length > bytes.length) return;
54
- cursor += length;
55
- if (marker === 218) {
56
- const eoi = indexOf(bytes, [255, 217], cursor);
57
- if (eoi === void 0) return;
58
- return {
45
+ try {
46
+ for (;;) {
47
+ if (require_bytes_view.byteAt(bytes, cursor) !== 255) return;
48
+ while (require_bytes_view.byteAt(bytes, cursor) === 255) cursor += 1;
49
+ const marker = require_bytes_view.byteAt(bytes, cursor);
50
+ cursor += 1;
51
+ if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) continue;
52
+ if (marker === 217) return {
59
53
  format: "jpeg",
60
- bytes: bytes.subarray(soiAt, eoi + 2)
54
+ bytes: bytes.subarray(soiAt, cursor)
61
55
  };
56
+ const length = bigEndianUint16At(bytes, cursor);
57
+ if (length < 2) return;
58
+ cursor += require_bytes_view.sliceAt(bytes, cursor, length).length;
59
+ if (marker === 218) {
60
+ const eoi = indexOf(bytes, [255, 217], cursor);
61
+ return {
62
+ format: "jpeg",
63
+ bytes: bytes.subarray(soiAt, eoi + 2)
64
+ };
65
+ }
62
66
  }
67
+ } catch {
68
+ return;
63
69
  }
64
70
  }
65
71
  function scanImagePayload(bytes) {
66
- const pngAt = indexOf(bytes, PNG_SIGNATURE, 0);
67
- const jpegAt = indexOf(bytes, JPEG_SOI, 0);
68
- if (pngAt !== void 0 && (jpegAt === void 0 || pngAt < jpegAt)) return scanPng(bytes, pngAt);
69
- if (jpegAt !== void 0) return scanJpeg(bytes, jpegAt);
72
+ try {
73
+ for (let index = 0;; index += 1) {
74
+ try {
75
+ if (bytesMatchAt(bytes, index, PNG_SIGNATURE)) return scanPng(bytes, index);
76
+ } catch {}
77
+ if (bytesMatchAt(bytes, index, JPEG_SOI)) return scanJpeg(bytes, index);
78
+ }
79
+ } catch {
80
+ return;
81
+ }
70
82
  }
71
83
  //#endregion
84
+ exports.bigEndianUint16At = bigEndianUint16At;
85
+ exports.bigEndianUint32At = bigEndianUint32At;
72
86
  exports.scanImagePayload = scanImagePayload;
@@ -3,6 +3,8 @@ interface WpdImagePayload {
3
3
  readonly format: "png" | "jpeg";
4
4
  readonly bytes: Uint8Array;
5
5
  }
6
+ declare function bigEndianUint32At(bytes: Uint8Array, offset: number): number;
7
+ declare function bigEndianUint16At(bytes: Uint8Array, offset: number): number;
6
8
  declare function scanImagePayload(bytes: Uint8Array): WpdImagePayload | undefined;
7
9
  //#endregion
8
- export { WpdImagePayload, scanImagePayload };
10
+ export { WpdImagePayload, bigEndianUint16At, bigEndianUint32At, scanImagePayload };
@@ -3,6 +3,8 @@ interface WpdImagePayload {
3
3
  readonly format: "png" | "jpeg";
4
4
  readonly bytes: Uint8Array;
5
5
  }
6
+ declare function bigEndianUint32At(bytes: Uint8Array, offset: number): number;
7
+ declare function bigEndianUint16At(bytes: Uint8Array, offset: number): number;
6
8
  declare function scanImagePayload(bytes: Uint8Array): WpdImagePayload | undefined;
7
9
  //#endregion
8
- export { WpdImagePayload, scanImagePayload };
10
+ export { WpdImagePayload, bigEndianUint16At, bigEndianUint32At, scanImagePayload };
@@ -1,4 +1,4 @@
1
- import { byteAt } from "../bytes/view.js";
1
+ import { byteAt, sliceAt } from "../bytes/view.js";
2
2
  //#region src/stream/image.ts
3
3
  const PNG_SIGNATURE = [
4
4
  137,
@@ -11,61 +11,73 @@ const PNG_SIGNATURE = [
11
11
  10
12
12
  ];
13
13
  const JPEG_SOI = [255, 216];
14
+ function bytesMatchAt(bytes, index, signature) {
15
+ return signature.every((byte, offset) => byteAt(bytes, index + offset) === byte);
16
+ }
14
17
  function indexOf(bytes, needle, from) {
15
- outer: for (let i = from; i + needle.length <= bytes.length; i += 1) {
16
- for (let j = 0; j < needle.length; j += 1) if (bytes[i + j] !== needle[j]) continue outer;
17
- return i;
18
- }
18
+ for (let index = from;; index += 1) if (bytesMatchAt(bytes, index, needle)) return index;
19
+ }
20
+ function bigEndianUint32At(bytes, offset) {
21
+ return byteAt(bytes, offset) * 16777216 + byteAt(bytes, offset + 1) * 65536 + byteAt(bytes, offset + 2) * 256 + byteAt(bytes, offset + 3);
22
+ }
23
+ function bigEndianUint16At(bytes, offset) {
24
+ return byteAt(bytes, offset) * 256 + byteAt(bytes, offset + 1);
19
25
  }
20
26
  function scanPng(bytes, signatureAt) {
21
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
22
27
  let cursor = signatureAt + PNG_SIGNATURE.length;
23
- for (;;) {
24
- if (cursor + 8 > bytes.length) return;
25
- const length = view.getUint32(cursor);
26
- const type = String.fromCharCode(byteAt(bytes, cursor + 4), byteAt(bytes, cursor + 5), byteAt(bytes, cursor + 6), byteAt(bytes, cursor + 7));
27
- cursor += 8 + length + 4;
28
- if (cursor > bytes.length) return;
29
- if (type === "IEND") return {
30
- format: "png",
31
- bytes: bytes.subarray(signatureAt, cursor)
32
- };
28
+ try {
29
+ for (;;) {
30
+ const length = bigEndianUint32At(bytes, cursor);
31
+ const type = String.fromCharCode(byteAt(bytes, cursor + 4), byteAt(bytes, cursor + 5), byteAt(bytes, cursor + 6), byteAt(bytes, cursor + 7));
32
+ cursor += 8 + length + 4;
33
+ if (type === "IEND") return {
34
+ format: "png",
35
+ bytes: sliceAt(bytes, signatureAt, cursor - signatureAt)
36
+ };
37
+ }
38
+ } catch {
39
+ return;
33
40
  }
34
41
  }
35
42
  function scanJpeg(bytes, soiAt) {
36
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
37
43
  let cursor = soiAt + JPEG_SOI.length;
38
- for (;;) {
39
- if (cursor >= bytes.length) return;
40
- if (byteAt(bytes, cursor) !== 255) return;
41
- while (cursor < bytes.length && byteAt(bytes, cursor) === 255) cursor += 1;
42
- if (cursor >= bytes.length) return;
43
- const marker = byteAt(bytes, cursor);
44
- cursor += 1;
45
- if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) continue;
46
- if (marker === 217) return {
47
- format: "jpeg",
48
- bytes: bytes.subarray(soiAt, cursor)
49
- };
50
- if (cursor + 2 > bytes.length) return;
51
- const length = view.getUint16(cursor);
52
- if (length < 2 || cursor + length > bytes.length) return;
53
- cursor += length;
54
- if (marker === 218) {
55
- const eoi = indexOf(bytes, [255, 217], cursor);
56
- if (eoi === void 0) return;
57
- return {
44
+ try {
45
+ for (;;) {
46
+ if (byteAt(bytes, cursor) !== 255) return;
47
+ while (byteAt(bytes, cursor) === 255) cursor += 1;
48
+ const marker = byteAt(bytes, cursor);
49
+ cursor += 1;
50
+ if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) continue;
51
+ if (marker === 217) return {
58
52
  format: "jpeg",
59
- bytes: bytes.subarray(soiAt, eoi + 2)
53
+ bytes: bytes.subarray(soiAt, cursor)
60
54
  };
55
+ const length = bigEndianUint16At(bytes, cursor);
56
+ if (length < 2) return;
57
+ cursor += sliceAt(bytes, cursor, length).length;
58
+ if (marker === 218) {
59
+ const eoi = indexOf(bytes, [255, 217], cursor);
60
+ return {
61
+ format: "jpeg",
62
+ bytes: bytes.subarray(soiAt, eoi + 2)
63
+ };
64
+ }
61
65
  }
66
+ } catch {
67
+ return;
62
68
  }
63
69
  }
64
70
  function scanImagePayload(bytes) {
65
- const pngAt = indexOf(bytes, PNG_SIGNATURE, 0);
66
- const jpegAt = indexOf(bytes, JPEG_SOI, 0);
67
- if (pngAt !== void 0 && (jpegAt === void 0 || pngAt < jpegAt)) return scanPng(bytes, pngAt);
68
- if (jpegAt !== void 0) return scanJpeg(bytes, jpegAt);
71
+ try {
72
+ for (let index = 0;; index += 1) {
73
+ try {
74
+ if (bytesMatchAt(bytes, index, PNG_SIGNATURE)) return scanPng(bytes, index);
75
+ } catch {}
76
+ if (bytesMatchAt(bytes, index, JPEG_SOI)) return scanJpeg(bytes, index);
77
+ }
78
+ } catch {
79
+ return;
80
+ }
69
81
  }
70
82
  //#endregion
71
- export { scanImagePayload };
83
+ export { bigEndianUint16At, bigEndianUint32At, scanImagePayload };
@@ -25,7 +25,7 @@ function readOleDescriptor(bytes) {
25
25
  let marker = "";
26
26
  for (let index = 0; index < 42; index += 1) marker += String.fromCharCode(require_bytes_view.byteAt(bytes, index));
27
27
  if (marker === OLE2_MARKER) {
28
- const { text } = require_stream_characters.decodeWordString(bytes, payloadOffset, (bytes.length - payloadOffset) / 2);
28
+ const { text } = require_stream_characters.decodeWordString(bytes, payloadOffset, require_stream_characters.UNBOUNDED_WORDS);
29
29
  if (text.length === 0) return;
30
30
  return {
31
31
  ole2: true,
@@ -1,5 +1,5 @@
1
1
  import { byteAt, uint16At, uint32At } from "../bytes/view.js";
2
- import { decodeWordString } from "./characters.js";
2
+ import { UNBOUNDED_WORDS, decodeWordString } from "./characters.js";
3
3
  import { packetByPrefixId } from "../container/prefix.js";
4
4
  //#region src/stream/ole.ts
5
5
  const PACKET_TYPE_GRAPHICS_FILENAME = 64;
@@ -24,7 +24,7 @@ function readOleDescriptor(bytes) {
24
24
  let marker = "";
25
25
  for (let index = 0; index < 42; index += 1) marker += String.fromCharCode(byteAt(bytes, index));
26
26
  if (marker === OLE2_MARKER) {
27
- const { text } = decodeWordString(bytes, payloadOffset, (bytes.length - payloadOffset) / 2);
27
+ const { text } = decodeWordString(bytes, payloadOffset, UNBOUNDED_WORDS);
28
28
  if (text.length === 0) return;
29
29
  return {
30
30
  ole2: true,