Skip to content

Commit

Permalink
chore(loader-utils): Preparing to migrate from FileProviders to Reada…
Browse files Browse the repository at this point in the history
…bleFiles (#3000)
  • Loading branch information
dariaterekhova-actionengine authored May 15, 2024
1 parent 48fda87 commit d9db370
Show file tree
Hide file tree
Showing 20 changed files with 248 additions and 60 deletions.
4 changes: 2 additions & 2 deletions examples/experimental/slpk-in-browser/src/browser-file.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import {FileProvider} from '@loaders.gl/loader-utils';
import {FileProviderInterface} from '@loaders.gl/loader-utils';

/**
* Provides file data using node fs library
* @deprecated - will be replaced with ReadableFile
*/
export class BrowserFile implements FileProvider {
export class BrowserFile implements FileProviderInterface {
/** The File object from which data is provided */
private file: File;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT
// Copyright vis.gl contributors

import {FileProvider} from '@loaders.gl/loader-utils';
import {FileProviderInterface} from '@loaders.gl/loader-utils';
import {MD5Hash} from '@loaders.gl/crypto';
import {DeflateCompression, NoCompression} from '@loaders.gl/compression';
import {IndexedArchive, parseZipLocalFileHeader} from '@loaders.gl/zip';
Expand Down Expand Up @@ -31,7 +31,11 @@ export class Tiles3DArchive extends IndexedArchive {
* @param fileProvider - FileProvider with the whole file
* @param hashTable - hash info
*/
constructor(fileProvider: FileProvider, hashTable?: Record<string, bigint>, fileName?: string) {
constructor(
fileProvider: FileProviderInterface,
hashTable?: Record<string, bigint>,
fileName?: string
) {
super(fileProvider, hashTable, fileName);
this.hashTable = hashTable;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT
// Copyright vis.gl contributors

import {FileProvider} from '@loaders.gl/loader-utils';
import {FileProviderInterface} from '@loaders.gl/loader-utils';
import {
CD_HEADER_SIGNATURE,
makeHashTableFromZipHeaders,
Expand All @@ -20,7 +20,7 @@ import {Tiles3DArchive} from './3d-tiles-archive-archive';
* @returns 3tz file handler
*/
export const parse3DTilesArchive = async (
fileProvider: FileProvider,
fileProvider: FileProviderInterface,
cb?: (msg: string) => void
): Promise<Tiles3DArchive> => {
const hashCDOffset = await searchFromTheEnd(fileProvider, CD_HEADER_SIGNATURE);
Expand Down
4 changes: 2 additions & 2 deletions modules/i3s/src/lib/parsers/parse-slpk/parse-slpk.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {FileProvider} from '@loaders.gl/loader-utils';
import {FileProviderInterface} from '@loaders.gl/loader-utils';
import {
parseZipCDFileHeader,
CD_HEADER_SIGNATURE,
Expand All @@ -16,7 +16,7 @@ import {SLPKArchive} from './slpk-archieve';
* @returns slpk file handler
*/
export async function parseSLPKArchive(
fileProvider: FileProvider,
fileProvider: FileProviderInterface,
cb?: (msg: string) => void,
fileName?: string
): Promise<SLPKArchive> {
Expand Down
8 changes: 6 additions & 2 deletions modules/i3s/src/lib/parsers/parse-slpk/slpk-archieve.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {MD5Hash} from '@loaders.gl/crypto';
import {FileProvider} from '@loaders.gl/loader-utils';
import {FileProviderInterface} from '@loaders.gl/loader-utils';
import {IndexedArchive, parseZipLocalFileHeader} from '@loaders.gl/zip';
import {GZipCompression} from '@loaders.gl/compression';

Expand Down Expand Up @@ -56,7 +56,11 @@ export class SLPKArchive extends IndexedArchive {
* @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file
* @param fileName - name of the archive. It is used to add to an URL of a loader context
*/
constructor(fileProvider: FileProvider, hashTable?: Record<string, bigint>, fileName?: string) {
constructor(
fileProvider: FileProviderInterface,
hashTable?: Record<string, bigint>,
fileName?: string
) {
super(fileProvider, hashTable, fileName);
this.hashTable = hashTable;
}
Expand Down
5 changes: 3 additions & 2 deletions modules/loader-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ export type {FileSystem, RandomAccessFileSystem} from './lib/filesystems/filesys
export {NodeFileSystemFacade as NodeFilesystem} from './lib/filesystems/node-filesystem-facade';

// TODO - replace with ReadableFile
export type {FileProvider} from './lib/file-provider/file-provider';
export {isFileProvider} from './lib/file-provider/file-provider';
export type {FileProviderInterface} from './lib/file-provider/file-provider-interface';
export {isFileProvider} from './lib/file-provider/file-provider-interface';
export {FileProvider} from './lib/file-provider/file-provider';
export {FileHandleFile} from './lib/file-provider/file-handle-file';
export {DataViewFile} from './lib/file-provider/data-view-file';

Expand Down
4 changes: 2 additions & 2 deletions modules/loader-utils/src/lib/file-provider/data-view-file.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {FileProvider} from './file-provider';
import {FileProviderInterface} from './file-provider-interface';

/**
* Checks if bigint can be converted to number and convert it if possible
Expand All @@ -16,7 +16,7 @@ const toNumber = (bigint: bigint) => {
* Provides file data using DataView
* @deprecated - will be replaced with ReadableFile
*/
export class DataViewFile implements FileProvider {
export class DataViewFile implements FileProviderInterface {
/** The DataView from which data is provided */
private file: DataView;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

import {FileProvider} from './file-provider';
import {FileProviderInterface} from './file-provider-interface';
import {NodeFileFacade as NodeFile} from '../files/node-file-facade';

/**
* Provides file data using node fs library
* @deprecated - will be replaced with ReadableFile
*/
export class FileHandleFile implements FileProvider {
export class FileHandleFile implements FileProviderInterface {
/** The FileHandle from which data is provided */
private file: NodeFile;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Interface for providing file data
*/
export interface FileProviderInterface {
/**
* Cleanup class data
*/
destroy(): Promise<void>;
/**
* Gets an unsigned 8-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in bytes, from the start of the file where to read the data.
*/
getUint8(offset: bigint): Promise<number>;

/**
* Gets an unsigned 16-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in bytes, from the start of the file where to read the data.
*/
getUint16(offset: bigint): Promise<number>;

/**
* Gets an unsigned 32-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in bytes, from the file of the view where to read the data.
*/
getUint32(offset: bigint): Promise<number>;

/**
* Gets an unsigned 32-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in byte, from the file of the view where to read the data.
*/
getBigUint64(offset: bigint): Promise<bigint>;

/**
* returns an ArrayBuffer whose contents are a copy of this file bytes from startOffset, inclusive, up to endOffset, exclusive.
* @param startOffset The offset, in bytes, from the start of the file where to start reading the data.
* @param endOffset The offset, in bytes, from the start of the file where to end reading the data.
*/
slice(startOffset: bigint, endOffset: bigint): Promise<ArrayBuffer>;

/**
* the length (in bytes) of the data.
*/
length: bigint;
}

/**
* Check is the object has FileProvider members
* @param fileProvider - tested object
*/
export const isFileProvider = (fileProvider: unknown) => {
return (
(fileProvider as FileProviderInterface)?.getUint8 &&
(fileProvider as FileProviderInterface)?.slice &&
(fileProvider as FileProviderInterface)?.length
);
};
120 changes: 95 additions & 25 deletions modules/loader-utils/src/lib/file-provider/file-provider.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,127 @@
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import {ReadableFile} from '../files/file';
import {FileProviderInterface} from './file-provider-interface';

/**
* Interface for providing file data
* Provides file data using range requests to the server
* @deprecated - will be replaced with ReadableFile
*/
export interface FileProvider {
export class FileProvider implements FileProviderInterface {
/** The File object from which data is provided */
private file: ReadableFile;
private size: bigint;

/** Create a new BrowserFile */
private constructor(file: ReadableFile, size: bigint | number) {
this.file = file;
this.size = BigInt(size);
}

static async create(file: ReadableFile): Promise<FileProvider> {
return new FileProvider(
file,
file.bigsize > 0n
? file.bigsize
: file.size > 0n
? file.size

Check warning on line 28 in modules/loader-utils/src/lib/file-provider/file-provider.ts

View workflow job for this annotation

GitHub Actions / test (20)

Expected indentation of 10 spaces but found 8
: (await file.stat?.())?.bigsize ?? 0n

Check warning on line 29 in modules/loader-utils/src/lib/file-provider/file-provider.ts

View workflow job for this annotation

GitHub Actions / test (20)

Expected indentation of 10 spaces but found 8
);
}

/**
* Cleanup class data
* Truncates the file descriptor.
* @param length desired file lenght
*/
destroy(): Promise<void>;
async truncate(length: number): Promise<void> {
throw new Error('file loaded via range requests cannot be changed');
}

/**
* Append data to a file.
* @param buffer data to append
*/
async append(buffer: Uint8Array): Promise<void> {
throw new Error('file loaded via range requests cannot be changed');
}

/** Close file */
async destroy(): Promise<void> {
throw new Error('file loaded via range requests cannot be changed');
}

/**
* Gets an unsigned 8-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in bytes, from the start of the file where to read the data.
*/
getUint8(offset: bigint): Promise<number>;
async getUint8(offset: number | bigint): Promise<number> {
const arrayBuffer = await this.file.read(offset, 1);
const val = new Uint8Array(arrayBuffer).at(0);
if (val === undefined) {
throw new Error('something went wrong');
}
return val;
}

/**
* Gets an unsigned 16-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in bytes, from the start of the file where to read the data.
*/
getUint16(offset: bigint): Promise<number>;
async getUint16(offset: number | bigint): Promise<number> {
const arrayBuffer = await this.file.read(offset, 2);
const val = new Uint16Array(arrayBuffer).at(0);
if (val === undefined) {
throw new Error('something went wrong');
}
return val;
}

/**
* Gets an unsigned 32-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in bytes, from the file of the view where to read the data.
* @param offset The offset, in bytes, from the start of the file where to read the data.
*/
getUint32(offset: bigint): Promise<number>;
async getUint32(offset: number | bigint): Promise<number> {
const arrayBuffer = await this.file.read(offset, 4);
const val = new Uint32Array(arrayBuffer).at(0);
if (val === undefined) {
throw new Error('something went wrong');
}
return val;
}

/**
* Gets an unsigned 32-bit integer at the specified byte offset from the start of the file.
* @param offset The offset, in byte, from the file of the view where to read the data.
* @param offset The offset, in bytes, from the start of the file where to read the data.
*/
getBigUint64(offset: bigint): Promise<bigint>;
async getBigUint64(offset: number | bigint): Promise<bigint> {
const arrayBuffer = await this.file.read(offset, 8);
const val = new BigInt64Array(arrayBuffer).at(0);
if (val === undefined) {
throw new Error('something went wrong');
}
return val;
}

/**
* returns an ArrayBuffer whose contents are a copy of this file bytes from startOffset, inclusive, up to endOffset, exclusive.
* @param startOffset The offset, in bytes, from the start of the file where to start reading the data.
* @param startOffset The offset, in byte, from the start of the file where to start reading the data.
* @param endOffset The offset, in bytes, from the start of the file where to end reading the data.
*/
slice(startOffset: bigint, endOffset: bigint): Promise<ArrayBuffer>;
async slice(startOffset: bigint | number, endOffset: bigint | number): Promise<ArrayBuffer> {
const bigLength = BigInt(endOffset) - BigInt(startOffset);
if (bigLength > Number.MAX_SAFE_INTEGER) {
throw new Error('too big slice');
}
const length = Number(bigLength);

return await this.file.read(startOffset, length);
}

/**
* the length (in bytes) of the data.
*/
length: bigint;
get length(): bigint {
return this.size;
}
}

/**
* Check is the object has FileProvider members
* @param fileProvider - tested object
*/
export const isFileProvider = (fileProvider: unknown) => {
return (
(fileProvider as FileProvider)?.getUint8 &&
(fileProvider as FileProvider)?.slice &&
(fileProvider as FileProvider)?.length
);
};
1 change: 1 addition & 0 deletions modules/loader-utils/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ import './lib/request-utils/request-scheduler.spec';

import './lib/file-provider/data-view-file.spec';
import './lib/file-provider/file-handle-file.spec';
import './lib/file-provider/file-provider.spec';

import './lib/worker-loader-utils/parse-with-worker.spec';
40 changes: 40 additions & 0 deletions modules/loader-utils/test/lib/file-provider/file-provider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import test from 'tape-promise/tape';
import {DATA_ARRAY} from '@loaders.gl/i3s/test/data/test.zip';
import {BlobFile, FileProvider} from '@loaders.gl/loader-utils';

export const getSignature = () => new Uint8Array([0x50, 0x4b, 0x03, 0x04]);

const getProvider = () => {
return FileProvider.create(new BlobFile(DATA_ARRAY.buffer));
};

test('FileProvider#slice', async (t) => {
const provider = await getProvider();
const slice = await provider.slice(0, 4);
t.deepEqual(new Uint8Array(slice), getSignature());
t.end();
});

test('FileProvider#getUint8', async (t) => {
const provider = await getProvider();
t.equals(await provider.getUint8(0), 80);
t.end();
});

test('FileProvider#getUint16', async (t) => {
const provider = await getProvider();
t.equals(await provider.getUint16(0), 19280);
t.end();
});

test('FileProvider#getUint32', async (t) => {
const provider = await getProvider();
t.equals(await provider.getUint32(0), 67324752);
t.end();
});

test('FileProvider#getBigUint64', async (t) => {
const provider = await getProvider();
t.equals(await provider.getBigUint64(0), 563035920091984n);
t.end();
});
Loading

0 comments on commit d9db370

Please sign in to comment.