Skip to content

Commit

Permalink
feat(zip): Added append and truncate functionality (#2800)
Browse files Browse the repository at this point in the history
  • Loading branch information
dariaterekhova-actionengine authored Dec 7, 2023
1 parent 08eddf1 commit c5ec864
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 13 deletions.
26 changes: 19 additions & 7 deletions modules/loader-utils/src/lib/file-provider/file-handle-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,25 @@ export class FileHandleFile implements FileProvider {
/** The FileHandle from which data is provided */
private file: NodeFile;

/** The file length in bytes */
private size: bigint;

/** Create a new FileHandleFile */
constructor(path: string) {
this.file = new NodeFile(path, 'r');
this.size = this.file.bigsize;
constructor(path: string, append: boolean = false) {
this.file = new NodeFile(path, append ? 'a+' : 'r');
}

/**
* Truncates the file descriptor.
* @param length desired file lenght
*/
async truncate(length: number): Promise<void> {
await this.file.truncate(length);
}

/**
* Append data to a file.
* @param buffer data to append
*/
async append(buffer: Uint8Array): Promise<void> {
await this.file.append(buffer);
}

/** Close file */
Expand Down Expand Up @@ -96,6 +108,6 @@ export class FileHandleFile implements FileProvider {
* the length (in bytes) of the data.
*/
get length(): bigint {
return this.size;
return this.file.bigsize;
}
}
12 changes: 11 additions & 1 deletion modules/loader-utils/src/lib/files/node-file-facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class NodeFileFacade implements ReadableFile, WritableFile {
bigsize: bigint = 0n;
url: string = '';

constructor(url: string, flags?: 'r' | 'w' | 'wx', mode?: number) {
constructor(url: string, flags?: 'r' | 'w' | 'wx' | 'a+', mode?: number) {
// Return the actual implementation instance
if (globalThis.loaders?.NodeFile) {
return new globalThis.loaders.NodeFile(url, flags, mode);
Expand All @@ -35,6 +35,16 @@ export class NodeFileFacade implements ReadableFile, WritableFile {
async stat(): Promise<Stat> {
throw NOT_IMPLEMENTED;
}

/** Truncates the file descriptor. Only available on NodeFile. */
async truncate(length: number): Promise<void> {
throw NOT_IMPLEMENTED;
}

/** Append data to a file. Only available on NodeFile. */
async append(data: Uint8Array): Promise<void> {
throw NOT_IMPLEMENTED;
}
/** Close the file */
async close(): Promise<void> {}
}
30 changes: 29 additions & 1 deletion modules/polyfills/src/filesystems/node-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class NodeFile implements ReadableFile, WritableFile {
bigsize: bigint;
url: string;

constructor(path: string, flags: 'r' | 'w' | 'wx', mode?: number) {
constructor(path: string, flags: 'r' | 'w' | 'wx' | 'a+', mode?: number) {
path = resolvePath(path);
this.handle = fs.openSync(path, flags, mode);
const stats = fs.fstatSync(this.handle, {bigint: true});
Expand All @@ -23,6 +23,34 @@ export class NodeFile implements ReadableFile, WritableFile {
});
}

async truncate(length: number): Promise<void> {
return new Promise((resolve, reject) => {
fs.ftruncate(this.handle, length, (err) => {
if (err) {
reject(err);
} else {
this.bigsize = BigInt(length);
this.size = Number(this.bigsize);
resolve();
}
});
});
}

async append(data: Uint8Array): Promise<void> {
return new Promise((resolve, reject) => {
fs.appendFile(this.handle, data, (err) => {
if (err) {
reject(err);
} else {
this.bigsize = this.bigsize + BigInt(data.length);
this.size = Number(this.bigsize);
resolve();
}
});
});
}

async stat(): Promise<Stat> {
return await new Promise((resolve, reject) =>
fs.fstat(this.handle, {bigint: true}, (err, info) => {
Expand Down
29 changes: 25 additions & 4 deletions modules/polyfills/test/filesystems/node-file.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,37 @@ import test from 'tape-promise/tape';
import {isBrowser} from '@loaders.gl/core';
import {NodeFile} from '@loaders.gl/loader-utils';

const SLPK_URL = '@loaders.gl/i3s/test/data/DA12_subset.slpk';
const SLPK_URL = 'modules/i3s/test/data/DA12_subset.slpk';
const TEST_OFFSET = 100n;

// TODO v4.0 restore this test
test.skip('NodeFile#open and read', async (t) => {
const getSize = async (provider: NodeFile): Promise<bigint> => {
const stat = await provider.stat();
return stat.bigsize;
};

test('NodeFile#open and read', async (t) => {
if (!isBrowser) {
const provider = new NodeFile(SLPK_URL);
const arrayBuffer = await provider.read(4, 1);

const reference = new Buffer(new Uint8Array([0]));
const reference = Buffer.from(new Uint8Array([0x2d]));
t.equals(reference.compare(Buffer.from(arrayBuffer)), 0);
}
t.end();
});

test('NodeFile#truncate and append', async (t) => {
if (!isBrowser) {
const provider = new NodeFile(SLPK_URL, 'a+');
const initialSize = await getSize(provider);

const ending = await provider.read(TEST_OFFSET, Number(initialSize - TEST_OFFSET));

await provider.truncate(Number(TEST_OFFSET));
t.equals(await getSize(provider), TEST_OFFSET);

await provider.append(new Uint8Array(ending));
t.equals(await getSize(provider), initialSize);
}
t.end();
});

0 comments on commit c5ec864

Please sign in to comment.