@loaders.gl/i3s 4.0.0-alpha.6 → 4.0.0-alpha.7

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 (83) hide show
  1. package/dist/dist.min.js +676 -113
  2. package/dist/es5/arcgis-webscene-loader.js +1 -1
  3. package/dist/es5/i3s-attribute-loader.js +1 -1
  4. package/dist/es5/i3s-building-scene-layer-loader.js +1 -1
  5. package/dist/es5/i3s-content-loader.js +2 -3
  6. package/dist/es5/i3s-content-loader.js.map +1 -1
  7. package/dist/es5/i3s-loader.js +1 -1
  8. package/dist/es5/i3s-node-page-loader.js +1 -1
  9. package/dist/es5/i3s-slpk-loader.js +20 -0
  10. package/dist/es5/i3s-slpk-loader.js.map +1 -0
  11. package/dist/es5/index.js +8 -1
  12. package/dist/es5/index.js.map +1 -1
  13. package/dist/es5/lib/parsers/parse-slpk/parse-slpk.js +94 -0
  14. package/dist/es5/lib/parsers/parse-slpk/parse-slpk.js.map +1 -0
  15. package/dist/es5/lib/parsers/parse-slpk/slpk-archieve.js +112 -0
  16. package/dist/es5/lib/parsers/parse-slpk/slpk-archieve.js.map +1 -0
  17. package/dist/es5/lib/parsers/parse-zip/cd-file-header.js +44 -0
  18. package/dist/es5/lib/parsers/parse-zip/cd-file-header.js.map +1 -0
  19. package/dist/es5/lib/parsers/parse-zip/local-file-header.js +26 -0
  20. package/dist/es5/lib/parsers/parse-zip/local-file-header.js.map +1 -0
  21. package/dist/es5/workers/{i3s-content-nodejs-worker.js → i3s-content-worker-node.js} +2 -2
  22. package/dist/es5/workers/i3s-content-worker-node.js.map +1 -0
  23. package/dist/esm/arcgis-webscene-loader.js +1 -1
  24. package/dist/esm/i3s-attribute-loader.js +1 -1
  25. package/dist/esm/i3s-building-scene-layer-loader.js +1 -1
  26. package/dist/esm/i3s-content-loader.js +2 -3
  27. package/dist/esm/i3s-content-loader.js.map +1 -1
  28. package/dist/esm/i3s-loader.js +1 -1
  29. package/dist/esm/i3s-node-page-loader.js +1 -1
  30. package/dist/esm/i3s-slpk-loader.js +13 -0
  31. package/dist/esm/i3s-slpk-loader.js.map +1 -0
  32. package/dist/esm/index.js +2 -1
  33. package/dist/esm/index.js.map +1 -1
  34. package/dist/esm/lib/parsers/parse-slpk/parse-slpk.js +37 -0
  35. package/dist/esm/lib/parsers/parse-slpk/parse-slpk.js.map +1 -0
  36. package/dist/esm/lib/parsers/parse-slpk/slpk-archieve.js +58 -0
  37. package/dist/esm/lib/parsers/parse-slpk/slpk-archieve.js.map +1 -0
  38. package/dist/esm/lib/parsers/parse-zip/cd-file-header.js +37 -0
  39. package/dist/esm/lib/parsers/parse-zip/cd-file-header.js.map +1 -0
  40. package/dist/esm/lib/parsers/parse-zip/local-file-header.js +19 -0
  41. package/dist/esm/lib/parsers/parse-zip/local-file-header.js.map +1 -0
  42. package/dist/esm/workers/{i3s-content-nodejs-worker.js → i3s-content-worker-node.js} +2 -2
  43. package/dist/esm/workers/i3s-content-worker-node.js.map +1 -0
  44. package/dist/i3s-content-loader.d.ts.map +1 -1
  45. package/dist/i3s-content-loader.js +1 -2
  46. package/dist/i3s-content-worker-node.js +197 -0
  47. package/dist/{i3s-content-nodejs-worker.js.map → i3s-content-worker-node.js.map} +3 -3
  48. package/dist/i3s-content-worker.js +77 -55
  49. package/dist/i3s-slpk-loader.d.ts +10 -0
  50. package/dist/i3s-slpk-loader.d.ts.map +1 -0
  51. package/dist/i3s-slpk-loader.js +20 -0
  52. package/dist/index.d.ts +2 -1
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +5 -3
  55. package/dist/lib/parsers/parse-slpk/parse-slpk.d.ts +4 -0
  56. package/dist/lib/parsers/parse-slpk/parse-slpk.d.ts.map +1 -0
  57. package/dist/lib/parsers/parse-slpk/parse-slpk.js +50 -0
  58. package/dist/lib/parsers/parse-slpk/slpk-archieve.d.ts +32 -0
  59. package/dist/lib/parsers/parse-slpk/slpk-archieve.d.ts.map +1 -0
  60. package/dist/lib/parsers/parse-slpk/slpk-archieve.js +79 -0
  61. package/dist/lib/parsers/parse-zip/cd-file-header.d.ts +38 -0
  62. package/dist/lib/parsers/parse-zip/cd-file-header.d.ts.map +1 -0
  63. package/dist/lib/parsers/parse-zip/cd-file-header.js +48 -0
  64. package/dist/lib/parsers/parse-zip/local-file-header.d.ts +30 -0
  65. package/dist/lib/parsers/parse-zip/local-file-header.d.ts.map +1 -0
  66. package/dist/lib/parsers/parse-zip/local-file-header.js +28 -0
  67. package/dist/workers/i3s-content-worker-node.d.ts +2 -0
  68. package/dist/workers/i3s-content-worker-node.d.ts.map +1 -0
  69. package/dist/workers/{i3s-content-nodejs-worker.js → i3s-content-worker-node.js} +2 -1
  70. package/package.json +15 -13
  71. package/src/i3s-content-loader.ts +1 -2
  72. package/src/i3s-slpk-loader.ts +25 -0
  73. package/src/index.ts +2 -2
  74. package/src/lib/parsers/parse-slpk/parse-slpk.ts +61 -0
  75. package/src/lib/parsers/parse-slpk/slpk-archieve.ts +108 -0
  76. package/src/lib/parsers/parse-zip/cd-file-header.ts +93 -0
  77. package/src/lib/parsers/parse-zip/local-file-header.ts +56 -0
  78. package/src/workers/{i3s-content-nodejs-worker.ts → i3s-content-worker-node.ts} +2 -1
  79. package/dist/es5/workers/i3s-content-nodejs-worker.js.map +0 -1
  80. package/dist/esm/workers/i3s-content-nodejs-worker.js.map +0 -1
  81. package/dist/i3s-content-nodejs-worker.js +0 -198
  82. package/dist/workers/i3s-content-nodejs-worker.d.ts +0 -2
  83. package/dist/workers/i3s-content-nodejs-worker.d.ts.map +0 -1
@@ -0,0 +1,30 @@
1
+ /**
2
+ * zip local file header info
3
+ * according to https://en.wikipedia.org/wiki/ZIP_(file_format)
4
+ */
5
+ export type ZipLocalFileHeader = {
6
+ /**
7
+ * File name length
8
+ */
9
+ fileNameLength: number;
10
+ /**
11
+ * Extra field length
12
+ */
13
+ extraFieldLength: number;
14
+ /**
15
+ * Offset of the file data
16
+ */
17
+ fileDataOffset: number;
18
+ /**
19
+ * Compressed size
20
+ */
21
+ compressedSize: number;
22
+ };
23
+ /**
24
+ * Parses local file header of zip file
25
+ * @param headerOffset - offset in the archive where header starts
26
+ * @param buffer - buffer containing whole array
27
+ * @returns Info from the header
28
+ */
29
+ export declare const parseZipLocalFileHeader: (headerOffset: number, buffer: DataView) => ZipLocalFileHeader;
30
+ //# sourceMappingURL=local-file-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-file-header.d.ts","sourceRoot":"","sources":["../../../../src/lib/parsers/parse-zip/local-file-header.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,iBACpB,MAAM,UACZ,QAAQ,KACf,kBAuBF,CAAC"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseZipLocalFileHeader = void 0;
4
+ /**
5
+ * Parses local file header of zip file
6
+ * @param headerOffset - offset in the archive where header starts
7
+ * @param buffer - buffer containing whole array
8
+ * @returns Info from the header
9
+ */
10
+ const parseZipLocalFileHeader = (headerOffset, buffer) => {
11
+ const offsets = {
12
+ COMPRESSED_SIZE_OFFSET: 18,
13
+ FILE_NAME_LENGTH_OFFSET: 26,
14
+ EXTRA_FIELD_LENGTH_OFFSET: 28,
15
+ FILE_NAME_OFFSET: 30
16
+ };
17
+ const fileNameLength = buffer.getUint16(headerOffset + offsets.FILE_NAME_LENGTH_OFFSET, true);
18
+ const extraFieldLength = buffer.getUint16(headerOffset + offsets.EXTRA_FIELD_LENGTH_OFFSET, true);
19
+ const fileDataOffset = headerOffset + offsets.FILE_NAME_OFFSET + fileNameLength + extraFieldLength;
20
+ const compressedSize = buffer.getUint32(headerOffset + offsets.COMPRESSED_SIZE_OFFSET, true);
21
+ return {
22
+ fileNameLength,
23
+ extraFieldLength,
24
+ fileDataOffset,
25
+ compressedSize
26
+ };
27
+ };
28
+ exports.parseZipLocalFileHeader = parseZipLocalFileHeader;
@@ -0,0 +1,2 @@
1
+ import '@loaders.gl/polyfills';
2
+ //# sourceMappingURL=i3s-content-worker-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i3s-content-worker-node.d.ts","sourceRoot":"","sources":["../../src/workers/i3s-content-worker-node.ts"],"names":[],"mappings":"AACA,OAAO,uBAAuB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const loader_utils_1 = require("@loaders.gl/loader-utils");
3
+ // Polyfills increases the bundle size significantly. Use it for NodeJS worker only
4
4
  require("@loaders.gl/polyfills");
5
+ const loader_utils_1 = require("@loaders.gl/loader-utils");
5
6
  const i3s_content_loader_1 = require("../i3s-content-loader");
6
7
  (0, loader_utils_1.createLoaderWorker)(i3s_content_loader_1.I3SContentLoader);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/i3s",
3
- "version": "4.0.0-alpha.6",
3
+ "version": "4.0.0-alpha.7",
4
4
  "description": "i3s .",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -27,25 +27,27 @@
27
27
  "README.md"
28
28
  ],
29
29
  "scripts": {
30
- "pre-build": "npm run build-bundle && npm run build-worker && npm run build-loader-worker-nodejs",
30
+ "pre-build": "npm run build-bundle && npm run build-worker && npm run build-worker-node",
31
31
  "build-bundle": "esbuild src/bundle.ts --bundle --outfile=dist/dist.min.js",
32
- "build-worker": "esbuild src/workers/i3s-content-worker.ts --bundle --outfile=dist/i3s-content-worker.js --define:__VERSION__=\\\"$npm_package_version\\\"",
33
- "build-loader-worker-nodejs": "esbuild src/workers/i3s-content-nodejs-worker.ts --outfile=dist/i3s-content-nodejs-worker.js --platform=node --target=esnext,node12 --minify --bundle --sourcemap --define:__VERSION__=\\\"$npm_package_version\\\""
32
+ "build-worker": "esbuild src/workers/i3s-content-worker.ts --outfile=dist/i3s-content-worker.js --target=esnext --bundle --define:__VERSION__=\\\"$npm_package_version\\\"",
33
+ "build-worker-node": "esbuild src/workers/i3s-content-worker-node.ts --outfile=dist/i3s-content-worker-node.js --platform=node --target=node16 --minify --bundle --sourcemap --define:__VERSION__=\\\"$npm_package_version\\\""
34
34
  },
35
35
  "dependencies": {
36
- "@loaders.gl/draco": "4.0.0-alpha.6",
37
- "@loaders.gl/images": "4.0.0-alpha.6",
38
- "@loaders.gl/loader-utils": "4.0.0-alpha.6",
39
- "@loaders.gl/schema": "4.0.0-alpha.6",
40
- "@loaders.gl/textures": "4.0.0-alpha.6",
41
- "@loaders.gl/tiles": "4.0.0-alpha.6",
36
+ "@loaders.gl/compression": "4.0.0-alpha.7",
37
+ "@loaders.gl/draco": "4.0.0-alpha.7",
38
+ "@loaders.gl/images": "4.0.0-alpha.7",
39
+ "@loaders.gl/loader-utils": "4.0.0-alpha.7",
40
+ "@loaders.gl/schema": "4.0.0-alpha.7",
41
+ "@loaders.gl/textures": "4.0.0-alpha.7",
42
+ "@loaders.gl/tiles": "4.0.0-alpha.7",
42
43
  "@luma.gl/constants": "^8.5.4",
43
44
  "@math.gl/core": "^3.5.1",
44
45
  "@math.gl/culling": "^3.5.1",
45
- "@math.gl/geospatial": "^3.5.1"
46
+ "@math.gl/geospatial": "^3.5.1",
47
+ "md5": "^2.3.0"
46
48
  },
47
49
  "peerDependencies": {
48
- "@loaders.gl/core": "4.0.0-alpha.5"
50
+ "@loaders.gl/core": "4.0.0-alpha.6"
49
51
  },
50
- "gitHead": "acc1985050dfaa0f1f0c066f8da5bce7454a046c"
52
+ "gitHead": "afb59c4d8e5d8ebb9c28f111cb0c96c5527d0ffd"
51
53
  }
@@ -1,4 +1,3 @@
1
- import {isBrowser} from '@loaders.gl/worker-utils';
2
1
  import type {LoaderWithParser, LoaderContext} from '@loaders.gl/loader-utils';
3
2
  import type {I3SLoaderOptions} from './i3s-loader';
4
3
  import {parseI3STileContent} from './lib/parsers/parse-i3s-tile-content';
@@ -13,7 +12,7 @@ const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'beta';
13
12
  */
14
13
  export const I3SContentLoader: LoaderWithParser = {
15
14
  name: 'I3S Content (Indexed Scene Layers)',
16
- id: isBrowser ? 'i3s-content' : 'i3s-content-nodejs',
15
+ id: 'i3s-content',
17
16
  module: 'i3s',
18
17
  worker: true,
19
18
  version: VERSION,
@@ -0,0 +1,25 @@
1
+ import {LoaderOptions, LoaderWithParser} from '@loaders.gl/loader-utils';
2
+ import {parseSLPK} from './lib/parsers/parse-slpk/parse-slpk';
3
+
4
+ // __VERSION__ is injected by babel-plugin-version-inline
5
+ // @ts-ignore TS2304: Cannot find name '__VERSION__'.
6
+ const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';
7
+
8
+ export type SLPKLoaderOptions = LoaderOptions & {
9
+ path?: string;
10
+ mode?: 'http' | 'raw';
11
+ };
12
+
13
+ /**
14
+ * Loader for SLPK - Scene Layer Package
15
+ */
16
+ export const SLPKLoader: LoaderWithParser = {
17
+ name: 'I3S SLPK (Scene Layer Package)',
18
+ id: 'slpk',
19
+ module: 'i3s',
20
+ version: VERSION,
21
+ mimeTypes: ['application/octet-stream'],
22
+ parse: parseSLPK,
23
+ extensions: ['slpk'],
24
+ options: {}
25
+ };
package/src/index.ts CHANGED
@@ -36,9 +36,9 @@ export type {
36
36
  export {COORDINATE_SYSTEM} from './lib/parsers/constants';
37
37
 
38
38
  export {I3SLoader} from './i3s-loader';
39
+ export {SLPKLoader} from './i3s-slpk-loader';
39
40
  export {I3SContentLoader} from './i3s-content-loader';
40
41
  export {I3SAttributeLoader, loadFeatureAttributes} from './i3s-attribute-loader';
41
- export {I3SNodePageLoader} from './i3s-node-page-loader';
42
42
  export {I3SBuildingSceneLayerLoader} from './i3s-building-scene-layer-loader';
43
-
43
+ export {I3SNodePageLoader} from './i3s-node-page-loader';
44
44
  export {ArcGisWebSceneLoader} from './arcgis-webscene-loader';
@@ -0,0 +1,61 @@
1
+ import type {SLPKLoaderOptions} from '../../../i3s-slpk-loader';
2
+ import {parseZipCDFileHeader} from '../parse-zip/cd-file-header';
3
+ import {parseZipLocalFileHeader} from '../parse-zip/local-file-header';
4
+ import {SLPKArchive} from './slpk-archieve';
5
+
6
+ /**
7
+ * Returns one byte from the provided buffer at the provided position
8
+ * @param offset - position where to read
9
+ * @param buffer - buffer to read
10
+ * @returns one byte from the provided buffer at the provided position
11
+ */
12
+ const getByteAt = (offset: number, buffer: DataView): number => {
13
+ return buffer.getUint8(buffer.byteOffset + offset);
14
+ };
15
+
16
+ export async function parseSLPK(data: ArrayBuffer, options: SLPKLoaderOptions = {}) {
17
+ const archive = new DataView(data);
18
+ const cdFileHeaderSignature = [80, 75, 1, 2];
19
+
20
+ const searchWindow = [
21
+ getByteAt(archive.byteLength - 1, archive),
22
+ getByteAt(archive.byteLength - 2, archive),
23
+ getByteAt(archive.byteLength - 3, archive),
24
+ undefined
25
+ ];
26
+
27
+ let hashCDOffset = 0;
28
+
29
+ // looking for the last record in the central directory
30
+ for (let i = archive.byteLength - 4; i > -1; i--) {
31
+ searchWindow[3] = searchWindow[2];
32
+ searchWindow[2] = searchWindow[1];
33
+ searchWindow[1] = searchWindow[0];
34
+ searchWindow[0] = getByteAt(i, archive);
35
+ if (searchWindow.every((val, index) => val === cdFileHeaderSignature[index])) {
36
+ hashCDOffset = i;
37
+ break;
38
+ }
39
+ }
40
+
41
+ const cdFileHeader = parseZipCDFileHeader(hashCDOffset, archive);
42
+
43
+ const textDecoder = new TextDecoder();
44
+ if (textDecoder.decode(cdFileHeader.fileName) !== '@specialIndexFileHASH128@') {
45
+ throw new Error('No hash file in slpk');
46
+ }
47
+
48
+ const localFileHeader = parseZipLocalFileHeader(cdFileHeader.localHeaderOffset, archive);
49
+
50
+ const fileDataOffset = localFileHeader.fileDataOffset;
51
+ const hashFile = archive.buffer.slice(
52
+ fileDataOffset,
53
+ fileDataOffset + localFileHeader.compressedSize
54
+ );
55
+
56
+ if (!hashFile) {
57
+ throw new Error('No hash file in slpk');
58
+ }
59
+
60
+ return await new SLPKArchive(data, hashFile).getFile(options.path ?? '');
61
+ }
@@ -0,0 +1,108 @@
1
+ import {processOnWorker} from '@loaders.gl/worker-utils';
2
+ import md5 from 'md5';
3
+ import {CompressionWorker} from '@loaders.gl/compression';
4
+ import {parseZipLocalFileHeader} from '../parse-zip/local-file-header';
5
+
6
+ /** Element of hash array */
7
+ type HashElement = {
8
+ /**
9
+ * File name hash
10
+ */
11
+ hash: Buffer;
12
+ /**
13
+ * File offset in the archive
14
+ */
15
+ offset: number;
16
+ };
17
+
18
+ /**
19
+ * Class for handling information about slpk file
20
+ */
21
+ export class SLPKArchive {
22
+ slpkArchive: DataView;
23
+ hashArray: {hash: Buffer; offset: number}[];
24
+ constructor(slpkArchiveBuffer: ArrayBuffer, hashFile: ArrayBuffer) {
25
+ this.slpkArchive = new DataView(slpkArchiveBuffer);
26
+ this.hashArray = this.parseHashFile(hashFile);
27
+ }
28
+
29
+ /**
30
+ * Reads hash file from buffer and returns it in ready-to-use form
31
+ * @param hashFile - bufer containing hash file
32
+ * @returns Array containing file info
33
+ */
34
+ private parseHashFile(hashFile: ArrayBuffer): HashElement[] {
35
+ const hashFileBuffer = Buffer.from(hashFile);
36
+ const hashArray: HashElement[] = [];
37
+ for (let i = 0; i < hashFileBuffer.buffer.byteLength; i = i + 24) {
38
+ const offsetBuffer = new DataView(
39
+ hashFileBuffer.buffer.slice(
40
+ hashFileBuffer.byteOffset + i + 16,
41
+ hashFileBuffer.byteOffset + i + 24
42
+ )
43
+ );
44
+ const offset = offsetBuffer.getUint32(offsetBuffer.byteOffset, true);
45
+ hashArray.push({
46
+ hash: Buffer.from(
47
+ hashFileBuffer.subarray(hashFileBuffer.byteOffset + i, hashFileBuffer.byteOffset + i + 16)
48
+ ),
49
+ offset
50
+ });
51
+ }
52
+ return hashArray;
53
+ }
54
+
55
+ /**
56
+ * Returns file with the given path from slpk archive
57
+ * @param path - path inside the slpk
58
+ * @param mode - currently only raw mode supported
59
+ * @returns buffer with ready to use file
60
+ */
61
+ async getFile(path: string, mode: 'http' | 'raw' = 'raw'): Promise<Buffer> {
62
+ if (mode === 'http') {
63
+ throw new Error('http mode is not supported');
64
+ }
65
+
66
+ const fileToDecompress = this.getFileBytes(`${path}.gz`);
67
+
68
+ if (fileToDecompress) {
69
+ const decompressedData = await processOnWorker(CompressionWorker, fileToDecompress, {
70
+ compression: 'gzip',
71
+ operation: 'decompress',
72
+ _workerType: 'test',
73
+ gzip: {}
74
+ });
75
+ return decompressedData;
76
+ }
77
+ const fileWithoutCompression = this.getFileBytes(path);
78
+ if (fileWithoutCompression) {
79
+ return Promise.resolve(Buffer.from(fileWithoutCompression));
80
+ }
81
+ throw new Error('No such file in the archieve');
82
+ }
83
+
84
+ /**
85
+ * Trying to get raw file data by adress
86
+ * @param path - path inside the archive
87
+ * @returns buffer with the raw file data
88
+ */
89
+ private getFileBytes(path: string): ArrayBuffer | undefined {
90
+ const nameHash = Buffer.from(md5(path), 'hex');
91
+ const fileInfo = this.hashArray.find((val) => Buffer.compare(val.hash, nameHash) === 0);
92
+ if (!fileInfo) {
93
+ return undefined;
94
+ }
95
+
96
+ const localFileHeader = parseZipLocalFileHeader(
97
+ this.slpkArchive.byteOffset + fileInfo?.offset,
98
+ this.slpkArchive
99
+ );
100
+
101
+ const compressedFile = this.slpkArchive.buffer.slice(
102
+ localFileHeader.fileDataOffset,
103
+ localFileHeader.fileDataOffset + localFileHeader.compressedSize
104
+ );
105
+
106
+ return compressedFile;
107
+ }
108
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * zip central directory file header info
3
+ * according to https://en.wikipedia.org/wiki/ZIP_(file_format)
4
+ */
5
+ export type ZipCDFileHeader = {
6
+ /**
7
+ * Compressed size
8
+ */
9
+ compressedSize: number;
10
+ /**
11
+ * Uncompressed size
12
+ */
13
+ uncompressedSize: number;
14
+ /**
15
+ * File name length
16
+ */
17
+ fileNameLength: number;
18
+ /**
19
+ * File name
20
+ */
21
+ fileName: ArrayBuffer;
22
+ /**
23
+ * Extra field offset
24
+ */
25
+ extraOffset: number;
26
+ /**
27
+ * Relative offset of local file header
28
+ */
29
+ localHeaderOffset: number;
30
+ };
31
+
32
+ /**
33
+ * Parses central directory file header of zip file
34
+ * @param headerOffset - offset in the archive where header starts
35
+ * @param buffer - buffer containing whole array
36
+ * @returns Info from the header
37
+ */
38
+ export const parseZipCDFileHeader = (headerOffset: number, buffer: DataView): ZipCDFileHeader => {
39
+ const offsets = {
40
+ CD_COMPRESSED_SIZE_OFFSET: 20,
41
+ CD_UNCOMPRESSED_SIZE_OFFSET: 24,
42
+ CD_FILE_NAME_LENGTH_OFFSET: 28,
43
+ CD_EXTRA_FIELD_LENGTH_OFFSET: 30,
44
+ CD_LOCAL_HEADER_OFFSET_OFFSET: 42,
45
+ CD_FILE_NAME_OFFSET: 46
46
+ };
47
+
48
+ const compressedSize = buffer.getUint32(headerOffset + offsets.CD_COMPRESSED_SIZE_OFFSET, true);
49
+
50
+ const uncompressedSize = buffer.getUint32(
51
+ headerOffset + offsets.CD_UNCOMPRESSED_SIZE_OFFSET,
52
+ true
53
+ );
54
+
55
+ const fileNameLength = buffer.getUint16(headerOffset + offsets.CD_FILE_NAME_LENGTH_OFFSET, true);
56
+
57
+ const fileName = buffer.buffer.slice(
58
+ headerOffset + offsets.CD_FILE_NAME_OFFSET,
59
+ headerOffset + offsets.CD_FILE_NAME_OFFSET + fileNameLength
60
+ );
61
+
62
+ const extraOffset = headerOffset + offsets.CD_FILE_NAME_OFFSET + fileNameLength;
63
+
64
+ const oldFormatOffset = buffer.getUint32(
65
+ headerOffset + offsets.CD_LOCAL_HEADER_OFFSET_OFFSET,
66
+ true
67
+ );
68
+
69
+ let fileDataOffset = oldFormatOffset;
70
+ if (fileDataOffset === 0xffffffff) {
71
+ let offsetInZip64Data = 4;
72
+ // looking for info that might be also be in zip64 extra field
73
+ if (compressedSize === 0xffffffff) {
74
+ offsetInZip64Data += 8;
75
+ }
76
+ if (uncompressedSize === 0xffffffff) {
77
+ offsetInZip64Data += 8;
78
+ }
79
+
80
+ // getUint32 needs to be replaced with getBigUint64 for archieves bigger than 2gb
81
+ fileDataOffset = buffer.getUint32(extraOffset + offsetInZip64Data, true); // setting it to the one from zip64
82
+ }
83
+ const localHeaderOffset = fileDataOffset;
84
+
85
+ return {
86
+ compressedSize,
87
+ uncompressedSize,
88
+ fileNameLength,
89
+ fileName,
90
+ extraOffset,
91
+ localHeaderOffset
92
+ };
93
+ };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * zip local file header info
3
+ * according to https://en.wikipedia.org/wiki/ZIP_(file_format)
4
+ */
5
+ export type ZipLocalFileHeader = {
6
+ /**
7
+ * File name length
8
+ */
9
+ fileNameLength: number;
10
+ /**
11
+ * Extra field length
12
+ */
13
+ extraFieldLength: number;
14
+ /**
15
+ * Offset of the file data
16
+ */
17
+ fileDataOffset: number;
18
+ /**
19
+ * Compressed size
20
+ */
21
+ compressedSize: number;
22
+ };
23
+
24
+ /**
25
+ * Parses local file header of zip file
26
+ * @param headerOffset - offset in the archive where header starts
27
+ * @param buffer - buffer containing whole array
28
+ * @returns Info from the header
29
+ */
30
+ export const parseZipLocalFileHeader = (
31
+ headerOffset: number,
32
+ buffer: DataView
33
+ ): ZipLocalFileHeader => {
34
+ const offsets = {
35
+ COMPRESSED_SIZE_OFFSET: 18,
36
+ FILE_NAME_LENGTH_OFFSET: 26,
37
+ EXTRA_FIELD_LENGTH_OFFSET: 28,
38
+ FILE_NAME_OFFSET: 30
39
+ };
40
+
41
+ const fileNameLength = buffer.getUint16(headerOffset + offsets.FILE_NAME_LENGTH_OFFSET, true);
42
+
43
+ const extraFieldLength = buffer.getUint16(headerOffset + offsets.EXTRA_FIELD_LENGTH_OFFSET, true);
44
+
45
+ const fileDataOffset =
46
+ headerOffset + offsets.FILE_NAME_OFFSET + fileNameLength + extraFieldLength;
47
+
48
+ const compressedSize = buffer.getUint32(headerOffset + offsets.COMPRESSED_SIZE_OFFSET, true);
49
+
50
+ return {
51
+ fileNameLength,
52
+ extraFieldLength,
53
+ fileDataOffset,
54
+ compressedSize
55
+ };
56
+ };
@@ -1,5 +1,6 @@
1
- import {createLoaderWorker} from '@loaders.gl/loader-utils';
1
+ // Polyfills increases the bundle size significantly. Use it for NodeJS worker only
2
2
  import '@loaders.gl/polyfills';
3
+ import {createLoaderWorker} from '@loaders.gl/loader-utils';
3
4
  import {I3SContentLoader} from '../i3s-content-loader';
4
5
 
5
6
  createLoaderWorker(I3SContentLoader);
@@ -1 +0,0 @@
1
- {"version":3,"file":"i3s-content-nodejs-worker.js","names":["_loaderUtils","require","_i3sContentLoader","createLoaderWorker","I3SContentLoader"],"sources":["../../../src/workers/i3s-content-nodejs-worker.ts"],"sourcesContent":["import {createLoaderWorker} from '@loaders.gl/loader-utils';\nimport '@loaders.gl/polyfills';\nimport {I3SContentLoader} from '../i3s-content-loader';\n\ncreateLoaderWorker(I3SContentLoader);\n"],"mappings":";;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACAA,OAAA;AACA,IAAAC,iBAAA,GAAAD,OAAA;AAEA,IAAAE,+BAAkB,EAACC,kCAAgB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"i3s-content-nodejs-worker.js","names":["createLoaderWorker","I3SContentLoader"],"sources":["../../../src/workers/i3s-content-nodejs-worker.ts"],"sourcesContent":["import {createLoaderWorker} from '@loaders.gl/loader-utils';\nimport '@loaders.gl/polyfills';\nimport {I3SContentLoader} from '../i3s-content-loader';\n\ncreateLoaderWorker(I3SContentLoader);\n"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,0BAA0B;AAC3D,OAAO,uBAAuB;AAC9B,SAAQC,gBAAgB,QAAO,uBAAuB;AAEtDD,kBAAkB,CAACC,gBAAgB,CAAC"}