@loaders.gl/zip 4.2.1 → 4.3.0-alpha.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.
@@ -4,11 +4,11 @@
4
4
  import { compareArrayBuffers, concatenateArrayBuffers } from '@loaders.gl/loader-utils';
5
5
  import { createZip64Info, setFieldToNumber } from "./zip64-info-generation.js";
6
6
  // offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)
7
- const COMPRESSION_METHOD_OFFSET = 8n;
8
- const COMPRESSED_SIZE_OFFSET = 18n;
9
- const UNCOMPRESSED_SIZE_OFFSET = 22n;
10
- const FILE_NAME_LENGTH_OFFSET = 26n;
11
- const EXTRA_FIELD_LENGTH_OFFSET = 28n;
7
+ const COMPRESSION_METHOD_OFFSET = 8;
8
+ const COMPRESSED_SIZE_OFFSET = 18;
9
+ const UNCOMPRESSED_SIZE_OFFSET = 22;
10
+ const FILE_NAME_LENGTH_OFFSET = 26;
11
+ const EXTRA_FIELD_LENGTH_OFFSET = 28;
12
12
  const FILE_NAME_OFFSET = 30n;
13
13
  export const signature = new Uint8Array([0x50, 0x4b, 0x03, 0x04]);
14
14
  /**
@@ -17,34 +17,34 @@ export const signature = new Uint8Array([0x50, 0x4b, 0x03, 0x04]);
17
17
  * @param buffer - buffer containing whole array
18
18
  * @returns Info from the header
19
19
  */
20
- export const parseZipLocalFileHeader = async (headerOffset, buffer) => {
21
- const magicBytes = await buffer.slice(headerOffset, headerOffset + 4n);
20
+ export const parseZipLocalFileHeader = async (headerOffset, file) => {
21
+ const mainHeader = new DataView(await file.slice(headerOffset, headerOffset + FILE_NAME_OFFSET));
22
+ const magicBytes = mainHeader.buffer.slice(0, 4);
22
23
  if (!compareArrayBuffers(magicBytes, signature)) {
23
24
  return null;
24
25
  }
25
- const fileNameLength = await buffer.getUint16(headerOffset + FILE_NAME_LENGTH_OFFSET);
26
- const fileName = new TextDecoder()
27
- .decode(await buffer.slice(headerOffset + FILE_NAME_OFFSET, headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength)))
28
- .split('\\')
29
- .join('/');
30
- const extraFieldLength = await buffer.getUint16(headerOffset + EXTRA_FIELD_LENGTH_OFFSET);
26
+ const fileNameLength = mainHeader.getUint16(FILE_NAME_LENGTH_OFFSET, true);
27
+ const extraFieldLength = mainHeader.getUint16(EXTRA_FIELD_LENGTH_OFFSET, true);
28
+ const additionalHeader = await file.slice(headerOffset + FILE_NAME_OFFSET, headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength));
29
+ const fileNameBuffer = additionalHeader.slice(0, fileNameLength);
30
+ const extraDataBuffer = new DataView(additionalHeader.slice(fileNameLength, additionalHeader.byteLength));
31
+ const fileName = new TextDecoder().decode(fileNameBuffer).split('\\').join('/');
31
32
  let fileDataOffset = headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength);
32
- const compressionMethod = await buffer.getUint16(headerOffset + COMPRESSION_METHOD_OFFSET);
33
- let compressedSize = BigInt(await buffer.getUint32(headerOffset + COMPRESSED_SIZE_OFFSET)); // add zip 64 logic
34
- let uncompressedSize = BigInt(await buffer.getUint32(headerOffset + UNCOMPRESSED_SIZE_OFFSET)); // add zip 64 logic
35
- const extraOffset = headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength);
36
- let offsetInZip64Data = 4n;
33
+ const compressionMethod = mainHeader.getUint16(COMPRESSION_METHOD_OFFSET, true);
34
+ let compressedSize = BigInt(mainHeader.getUint32(COMPRESSED_SIZE_OFFSET, true)); // add zip 64 logic
35
+ let uncompressedSize = BigInt(mainHeader.getUint32(UNCOMPRESSED_SIZE_OFFSET, true)); // add zip 64 logic
36
+ let offsetInZip64Data = 4;
37
37
  // looking for info that might be also be in zip64 extra field
38
38
  if (uncompressedSize === BigInt(0xffffffff)) {
39
- uncompressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data);
40
- offsetInZip64Data += 8n;
39
+ uncompressedSize = extraDataBuffer.getBigUint64(offsetInZip64Data, true);
40
+ offsetInZip64Data += 8;
41
41
  }
42
42
  if (compressedSize === BigInt(0xffffffff)) {
43
- compressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data);
44
- offsetInZip64Data += 8n;
43
+ compressedSize = extraDataBuffer.getBigUint64(offsetInZip64Data, true);
44
+ offsetInZip64Data += 8;
45
45
  }
46
46
  if (fileDataOffset === BigInt(0xffffffff)) {
47
- fileDataOffset = await buffer.getBigUint64(extraOffset + offsetInZip64Data); // setting it to the one from zip64
47
+ fileDataOffset = extraDataBuffer.getBigUint64(offsetInZip64Data, true); // setting it to the one from zip64
48
48
  }
49
49
  return {
50
50
  fileNameLength,
@@ -1 +1 @@
1
- {"version":3,"file":"search-from-the-end.d.ts","sourceRoot":"","sources":["../../src/parse-zip/search-from-the-end.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAEtD,wCAAwC;AACxC,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,SACrB,YAAY,UACV,YAAY,KACnB,QAAQ,MAAM,CAuBhB,CAAC"}
1
+ {"version":3,"file":"search-from-the-end.d.ts","sourceRoot":"","sources":["../../src/parse-zip/search-from-the-end.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAEtD,wCAAwC;AACxC,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAItC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,SACrB,YAAY,UACV,YAAY,KACnB,QAAQ,MAAM,CA8BhB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  // loaders.gl
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
+ const buffLength = 1024;
4
5
  /**
5
6
  * looking for the last occurrence of the provided
6
7
  * @param file
@@ -14,17 +15,24 @@ export const searchFromTheEnd = async (file, target) => {
14
15
  await file.getUint8(file.length - 3n),
15
16
  undefined
16
17
  ];
17
- let targetOffset = 0n;
18
+ let targetOffset = -1;
18
19
  // looking for the last record in the central directory
19
- for (let i = file.length - 4n; i > -1; i--) {
20
- searchWindow[3] = searchWindow[2];
21
- searchWindow[2] = searchWindow[1];
22
- searchWindow[1] = searchWindow[0];
23
- searchWindow[0] = await file.getUint8(i);
24
- if (searchWindow.every((val, index) => val === target[index])) {
25
- targetOffset = i;
26
- break;
20
+ let point = file.length - 4n;
21
+ do {
22
+ const prevPoint = point;
23
+ point -= BigInt(buffLength);
24
+ point = point >= 0n ? point : 0n;
25
+ const buff = new Uint8Array(await file.slice(point, prevPoint));
26
+ for (let i = buff.length - 1; i > -1; i--) {
27
+ searchWindow[3] = searchWindow[2];
28
+ searchWindow[2] = searchWindow[1];
29
+ searchWindow[1] = searchWindow[0];
30
+ searchWindow[0] = buff[i];
31
+ if (searchWindow.every((val, index) => val === target[index])) {
32
+ targetOffset = i;
33
+ break;
34
+ }
27
35
  }
28
- }
29
- return targetOffset;
36
+ } while (targetOffset === -1 && point > 0n);
37
+ return point + BigInt(targetOffset);
30
38
  };
@@ -4,7 +4,7 @@
4
4
  import JSZip from 'jszip';
5
5
  // __VERSION__ is injected by babel-plugin-version-inline
6
6
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
7
- const VERSION = typeof "4.2.0" !== 'undefined' ? "4.2.0" : 'latest';
7
+ const VERSION = typeof "4.3.0-alpha.1" !== 'undefined' ? "4.3.0-alpha.1" : 'latest';
8
8
  export const ZipLoader = {
9
9
  dataType: null,
10
10
  batchType: null,
@@ -3,7 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
  import JSZip from 'jszip';
5
5
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
6
- const VERSION = typeof "4.2.0" !== 'undefined' ? "4.2.0" : 'latest';
6
+ const VERSION = typeof "4.3.0-alpha.1" !== 'undefined' ? "4.3.0-alpha.1" : 'latest';
7
7
  /**
8
8
  * Zip exporter
9
9
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/zip",
3
- "version": "4.2.1",
3
+ "version": "4.3.0-alpha.2",
4
4
  "description": "Zip Archive Loader",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -39,14 +39,14 @@
39
39
  "build-bundle-dev": "ocular-bundle ./bundle.ts --env=dev --output=dist/dist.dev.js"
40
40
  },
41
41
  "dependencies": {
42
- "@loaders.gl/compression": "4.2.1",
43
- "@loaders.gl/crypto": "4.2.1",
44
- "@loaders.gl/loader-utils": "4.2.1",
42
+ "@loaders.gl/compression": "4.3.0-alpha.2",
43
+ "@loaders.gl/crypto": "4.3.0-alpha.2",
44
+ "@loaders.gl/loader-utils": "4.3.0-alpha.2",
45
45
  "jszip": "^3.1.5",
46
46
  "md5": "^2.3.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@loaders.gl/core": "^4.0.0"
50
50
  },
51
- "gitHead": "b2ea799ff9f233ab8af0a6c3696e28ddf6e3c5a3"
51
+ "gitHead": "77a3cb538ab7a1fbf74245f25590210451689f5c"
52
52
  }
@@ -2,7 +2,12 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {FileProvider, compareArrayBuffers, concatenateArrayBuffers} from '@loaders.gl/loader-utils';
5
+ import {
6
+ DataViewFile,
7
+ FileProvider,
8
+ compareArrayBuffers,
9
+ concatenateArrayBuffers
10
+ } from '@loaders.gl/loader-utils';
6
11
  import {parseEoCDRecord} from './end-of-central-directory';
7
12
  import {ZipSignature} from './search-from-the-end';
8
13
  import {createZip64Info, setFieldToNumber} from './zip64-info-generation';
@@ -43,12 +48,12 @@ type Zip64Data = {
43
48
  };
44
49
 
45
50
  // offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)
46
- const CD_COMPRESSED_SIZE_OFFSET = 20n;
47
- const CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
48
- const CD_FILE_NAME_LENGTH_OFFSET = 28n;
49
- const CD_EXTRA_FIELD_LENGTH_OFFSET = 30n;
50
- const CD_START_DISK_OFFSET = 32n;
51
- const CD_LOCAL_HEADER_OFFSET_OFFSET = 42n;
51
+ const CD_COMPRESSED_SIZE_OFFSET = 20;
52
+ const CD_UNCOMPRESSED_SIZE_OFFSET = 24;
53
+ const CD_FILE_NAME_LENGTH_OFFSET = 28;
54
+ const CD_EXTRA_FIELD_LENGTH_OFFSET = 30;
55
+ const CD_START_DISK_OFFSET = 32;
56
+ const CD_LOCAL_HEADER_OFFSET_OFFSET = 42;
52
57
  const CD_FILE_NAME_OFFSET = 46n;
53
58
 
54
59
  export const signature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x01, 0x02]);
@@ -63,28 +68,38 @@ export const parseZipCDFileHeader = async (
63
68
  headerOffset: bigint,
64
69
  file: FileProvider
65
70
  ): Promise<ZipCDFileHeader | null> => {
66
- const magicBytes = await file.slice(headerOffset, headerOffset + 4n);
71
+ if (headerOffset >= file.length) {
72
+ return null;
73
+ }
74
+ const mainHeader = new DataView(
75
+ await file.slice(headerOffset, headerOffset + CD_FILE_NAME_OFFSET)
76
+ );
77
+
78
+ const magicBytes = mainHeader.buffer.slice(0, 4);
67
79
  if (!compareArrayBuffers(magicBytes, signature.buffer)) {
68
80
  return null;
69
81
  }
70
82
 
71
- const compressedSize = BigInt(await file.getUint32(headerOffset + CD_COMPRESSED_SIZE_OFFSET));
72
- const uncompressedSize = BigInt(await file.getUint32(headerOffset + CD_UNCOMPRESSED_SIZE_OFFSET));
73
- const extraFieldLength = await file.getUint16(headerOffset + CD_EXTRA_FIELD_LENGTH_OFFSET);
74
- const startDisk = BigInt(await file.getUint16(headerOffset + CD_START_DISK_OFFSET));
75
- const fileNameLength = await file.getUint16(headerOffset + CD_FILE_NAME_LENGTH_OFFSET);
76
- const filenameBytes = await file.slice(
83
+ const compressedSize = BigInt(mainHeader.getUint32(CD_COMPRESSED_SIZE_OFFSET, true));
84
+ const uncompressedSize = BigInt(mainHeader.getUint32(CD_UNCOMPRESSED_SIZE_OFFSET, true));
85
+ const extraFieldLength = mainHeader.getUint16(CD_EXTRA_FIELD_LENGTH_OFFSET, true);
86
+ const startDisk = BigInt(mainHeader.getUint16(CD_START_DISK_OFFSET, true));
87
+ const fileNameLength = mainHeader.getUint16(CD_FILE_NAME_LENGTH_OFFSET, true);
88
+
89
+ const additionalHeader = await file.slice(
77
90
  headerOffset + CD_FILE_NAME_OFFSET,
78
- headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength)
91
+ headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength)
79
92
  );
93
+
94
+ const filenameBytes = additionalHeader.slice(0, fileNameLength);
80
95
  const fileName = new TextDecoder().decode(filenameBytes);
81
96
 
82
97
  const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);
83
- const oldFormatOffset = await file.getUint32(headerOffset + CD_LOCAL_HEADER_OFFSET_OFFSET);
98
+ const oldFormatOffset = mainHeader.getUint32(CD_LOCAL_HEADER_OFFSET_OFFSET, true);
84
99
 
85
100
  const localHeaderOffset = BigInt(oldFormatOffset);
86
101
  const extraField = new DataView(
87
- await file.slice(extraOffset, extraOffset + BigInt(extraFieldLength))
102
+ additionalHeader.slice(fileNameLength, additionalHeader.byteLength)
88
103
  );
89
104
  // looking for info that might be also be in zip64 extra field
90
105
 
@@ -114,13 +129,16 @@ export const parseZipCDFileHeader = async (
114
129
  export async function* makeZipCDHeaderIterator(
115
130
  fileProvider: FileProvider
116
131
  ): AsyncIterable<ZipCDFileHeader> {
117
- const {cdStartOffset} = await parseEoCDRecord(fileProvider);
118
- let cdHeader = await parseZipCDFileHeader(cdStartOffset, fileProvider);
132
+ const {cdStartOffset, cdByteSize} = await parseEoCDRecord(fileProvider);
133
+ const centralDirectory = new DataViewFile(
134
+ new DataView(await fileProvider.slice(cdStartOffset, cdStartOffset + cdByteSize))
135
+ );
136
+ let cdHeader = await parseZipCDFileHeader(0n, centralDirectory);
119
137
  while (cdHeader) {
120
138
  yield cdHeader;
121
139
  cdHeader = await parseZipCDFileHeader(
122
140
  cdHeader.extraOffset + BigInt(cdHeader.extraFieldLength),
123
- fileProvider
141
+ centralDirectory
124
142
  );
125
143
  }
126
144
  }
@@ -11,10 +11,12 @@ import {setFieldToNumber} from './zip64-info-generation';
11
11
  * according to https://en.wikipedia.org/wiki/ZIP_(file_format)
12
12
  */
13
13
  export type ZipEoCDRecord = {
14
- /** Relative offset of local file header */
14
+ /** Relative offset of cd start */
15
15
  cdStartOffset: bigint;
16
- /** Relative offset of local file header */
16
+ /** Total number of central directory records */
17
17
  cdRecordsNumber: bigint;
18
+ /** Size of central directory */
19
+ cdByteSize: bigint;
18
20
  offsets: ZipEoCDRecordOffsets;
19
21
  };
20
22
 
@@ -66,6 +68,7 @@ export const parseEoCDRecord = async (file: FileProvider): Promise<ZipEoCDRecord
66
68
  const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
67
69
 
68
70
  let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));
71
+ let cdByteSize = BigInt(await file.getUint32(zipEoCDOffset + CD_CD_BYTE_SIZE_OFFSET));
69
72
  let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET));
70
73
 
71
74
  let zip64EoCDLocatorOffset = zipEoCDOffset - 20n;
@@ -83,6 +86,7 @@ export const parseEoCDRecord = async (file: FileProvider): Promise<ZipEoCDRecord
83
86
  }
84
87
 
85
88
  cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);
89
+ cdByteSize = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_CD_BYTE_SIZE_OFFSET);
86
90
  cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);
87
91
  } else {
88
92
  zip64EoCDLocatorOffset = 0n;
@@ -91,6 +95,7 @@ export const parseEoCDRecord = async (file: FileProvider): Promise<ZipEoCDRecord
91
95
  return {
92
96
  cdRecordsNumber,
93
97
  cdStartOffset,
98
+ cdByteSize,
94
99
  offsets: {
95
100
  zip64EoCDOffset,
96
101
  zip64EoCDLocatorOffset,
@@ -26,11 +26,11 @@ export type ZipLocalFileHeader = {
26
26
  };
27
27
 
28
28
  // offsets accroding to https://en.wikipedia.org/wiki/ZIP_(file_format)
29
- const COMPRESSION_METHOD_OFFSET = 8n;
30
- const COMPRESSED_SIZE_OFFSET = 18n;
31
- const UNCOMPRESSED_SIZE_OFFSET = 22n;
32
- const FILE_NAME_LENGTH_OFFSET = 26n;
33
- const EXTRA_FIELD_LENGTH_OFFSET = 28n;
29
+ const COMPRESSION_METHOD_OFFSET = 8;
30
+ const COMPRESSED_SIZE_OFFSET = 18;
31
+ const UNCOMPRESSED_SIZE_OFFSET = 22;
32
+ const FILE_NAME_LENGTH_OFFSET = 26;
33
+ const EXTRA_FIELD_LENGTH_OFFSET = 28;
34
34
  const FILE_NAME_OFFSET = 30n;
35
35
 
36
36
  export const signature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x03, 0x04]);
@@ -43,48 +43,52 @@ export const signature: ZipSignature = new Uint8Array([0x50, 0x4b, 0x03, 0x04]);
43
43
  */
44
44
  export const parseZipLocalFileHeader = async (
45
45
  headerOffset: bigint,
46
- buffer: FileProvider
46
+ file: FileProvider
47
47
  ): Promise<ZipLocalFileHeader | null> => {
48
- const magicBytes = await buffer.slice(headerOffset, headerOffset + 4n);
48
+ const mainHeader = new DataView(await file.slice(headerOffset, headerOffset + FILE_NAME_OFFSET));
49
+
50
+ const magicBytes = mainHeader.buffer.slice(0, 4);
49
51
  if (!compareArrayBuffers(magicBytes, signature)) {
50
52
  return null;
51
53
  }
52
54
 
53
- const fileNameLength = await buffer.getUint16(headerOffset + FILE_NAME_LENGTH_OFFSET);
55
+ const fileNameLength = mainHeader.getUint16(FILE_NAME_LENGTH_OFFSET, true);
54
56
 
55
- const fileName = new TextDecoder()
56
- .decode(
57
- await buffer.slice(
58
- headerOffset + FILE_NAME_OFFSET,
59
- headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength)
60
- )
61
- )
62
- .split('\\')
63
- .join('/');
64
- const extraFieldLength = await buffer.getUint16(headerOffset + EXTRA_FIELD_LENGTH_OFFSET);
57
+ const extraFieldLength = mainHeader.getUint16(EXTRA_FIELD_LENGTH_OFFSET, true);
65
58
 
66
- let fileDataOffset = headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength);
59
+ const additionalHeader = await file.slice(
60
+ headerOffset + FILE_NAME_OFFSET,
61
+ headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength)
62
+ );
63
+
64
+ const fileNameBuffer = additionalHeader.slice(0, fileNameLength);
67
65
 
68
- const compressionMethod = await buffer.getUint16(headerOffset + COMPRESSION_METHOD_OFFSET);
66
+ const extraDataBuffer = new DataView(
67
+ additionalHeader.slice(fileNameLength, additionalHeader.byteLength)
68
+ );
69
+
70
+ const fileName = new TextDecoder().decode(fileNameBuffer).split('\\').join('/');
71
+
72
+ let fileDataOffset = headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength);
69
73
 
70
- let compressedSize = BigInt(await buffer.getUint32(headerOffset + COMPRESSED_SIZE_OFFSET)); // add zip 64 logic
74
+ const compressionMethod = mainHeader.getUint16(COMPRESSION_METHOD_OFFSET, true);
71
75
 
72
- let uncompressedSize = BigInt(await buffer.getUint32(headerOffset + UNCOMPRESSED_SIZE_OFFSET)); // add zip 64 logic
76
+ let compressedSize = BigInt(mainHeader.getUint32(COMPRESSED_SIZE_OFFSET, true)); // add zip 64 logic
73
77
 
74
- const extraOffset = headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength);
78
+ let uncompressedSize = BigInt(mainHeader.getUint32(UNCOMPRESSED_SIZE_OFFSET, true)); // add zip 64 logic
75
79
 
76
- let offsetInZip64Data = 4n;
80
+ let offsetInZip64Data = 4;
77
81
  // looking for info that might be also be in zip64 extra field
78
82
  if (uncompressedSize === BigInt(0xffffffff)) {
79
- uncompressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data);
80
- offsetInZip64Data += 8n;
83
+ uncompressedSize = extraDataBuffer.getBigUint64(offsetInZip64Data, true);
84
+ offsetInZip64Data += 8;
81
85
  }
82
86
  if (compressedSize === BigInt(0xffffffff)) {
83
- compressedSize = await buffer.getBigUint64(extraOffset + offsetInZip64Data);
84
- offsetInZip64Data += 8n;
87
+ compressedSize = extraDataBuffer.getBigUint64(offsetInZip64Data, true);
88
+ offsetInZip64Data += 8;
85
89
  }
86
90
  if (fileDataOffset === BigInt(0xffffffff)) {
87
- fileDataOffset = await buffer.getBigUint64(extraOffset + offsetInZip64Data); // setting it to the one from zip64
91
+ fileDataOffset = extraDataBuffer.getBigUint64(offsetInZip64Data, true); // setting it to the one from zip64
88
92
  }
89
93
 
90
94
  return {
@@ -7,6 +7,8 @@ import {FileProvider} from '@loaders.gl/loader-utils';
7
7
  /** Description of zip signature type */
8
8
  export type ZipSignature = Uint8Array;
9
9
 
10
+ const buffLength = 1024;
11
+
10
12
  /**
11
13
  * looking for the last occurrence of the provided
12
14
  * @param file
@@ -24,19 +26,26 @@ export const searchFromTheEnd = async (
24
26
  undefined
25
27
  ];
26
28
 
27
- let targetOffset = 0n;
29
+ let targetOffset = -1;
28
30
 
29
31
  // looking for the last record in the central directory
30
- for (let i = file.length - 4n; i > -1; i--) {
31
- searchWindow[3] = searchWindow[2];
32
- searchWindow[2] = searchWindow[1];
33
- searchWindow[1] = searchWindow[0];
34
- searchWindow[0] = await file.getUint8(i);
35
- if (searchWindow.every((val, index) => val === target[index])) {
36
- targetOffset = i;
37
- break;
32
+ let point = file.length - 4n;
33
+ do {
34
+ const prevPoint = point;
35
+ point -= BigInt(buffLength);
36
+ point = point >= 0n ? point : 0n;
37
+ const buff = new Uint8Array(await file.slice(point, prevPoint));
38
+ for (let i = buff.length - 1; i > -1; i--) {
39
+ searchWindow[3] = searchWindow[2];
40
+ searchWindow[2] = searchWindow[1];
41
+ searchWindow[1] = searchWindow[0];
42
+ searchWindow[0] = buff[i];
43
+ if (searchWindow.every((val, index) => val === target[index])) {
44
+ targetOffset = i;
45
+ break;
46
+ }
38
47
  }
39
- }
48
+ } while (targetOffset === -1 && point > 0n);
40
49
 
41
- return targetOffset;
50
+ return point + BigInt(targetOffset);
42
51
  };