diff --git a/packages/core/src/binary/__test__/binary.header.test.ts b/packages/core/src/binary/__test__/binary.header.test.ts index 7539a556..019f2be4 100644 --- a/packages/core/src/binary/__test__/binary.header.test.ts +++ b/packages/core/src/binary/__test__/binary.header.test.ts @@ -1,6 +1,6 @@ import o from 'ospec'; import { writeHeaderFooter } from '../binary.index.builder.js'; -import { CotarMetadataParser } from '../binary.index.js'; +import { readMetadata } from '../binary.index.js'; const Example = { v1: { @@ -32,15 +32,13 @@ o.spec('CotarBinaryHeaderFooter', () => { }); o('should parse v1 header', () => { - const header = CotarMetadataParser.read(Example.v1.buf); - o(header.offset).equals(8); - o(header.value).deepEquals(Example.v1.header); + const header = readMetadata(Example.v1.buf); + o(header).deepEquals(Example.v1.header); }); o('should parse v2 header', () => { - const header = CotarMetadataParser.read(Example.v2.buf); - o(header.offset).equals(8); - o(header.value).deepEquals(Example.v2.header); + const header = readMetadata(Example.v2.buf); + o(header).deepEquals(Example.v2.header); }); o('should write a header and a footer', () => { @@ -52,10 +50,10 @@ o.spec('CotarBinaryHeaderFooter', () => { o(buf64.startsWith('Q09UAtIClkk')).equals(true); o(buf64.endsWith('Q09UAtIClkk=')).equals(true); - const headStart = CotarMetadataParser.read(buf); - const headEnd = CotarMetadataParser.read(buf, buf.length - 8); + const headStart = readMetadata(buf); + const headEnd = readMetadata(buf.slice(buf.length - 8)); - o(headStart.value).deepEquals(Example.v2.header); - o(headEnd.value).deepEquals(Example.v2.header); + o(headStart).deepEquals(Example.v2.header); + o(headEnd).deepEquals(Example.v2.header); }); }); diff --git a/packages/core/src/binary/binary.index.ts b/packages/core/src/binary/binary.index.ts index c30b35b2..aecaf2ea 100644 --- a/packages/core/src/binary/binary.index.ts +++ b/packages/core/src/binary/binary.index.ts @@ -1,6 +1,5 @@ import { ChunkSource } from '@chunkd/core'; import fnv1a from '@sindresorhus/fnv1a'; -import { bp } from 'binparse'; import { CotarIndexRecord } from '../cotar.js'; import { IndexHeaderSize, IndexMagic, IndexV1RecordSize, IndexV2RecordSize } from './format.js'; @@ -8,11 +7,24 @@ const Big0 = BigInt(0); const Big32 = BigInt(32); const BigUint32Max = BigInt(2 ** 32 - 1); -export const CotarMetadataParser = bp.object('CotarMetadata', { - magic: bp.string(IndexMagic.length), - version: bp.u8, - count: bp.lu32, -}); +export function readMetadata(bytes: Uint8Array): CotarMetadata { + // Read the first three bytes as magic 'COT' string + const magic = String.fromCharCode(bytes[0]) + String.fromCharCode(bytes[1]) + String.fromCharCode(bytes[2]); + + // Version number is a uint8 + const version = bytes[3]; + + // Record count from uint32 + const byteA = bytes[4]; + const byteB = bytes[5] << 8; + const byteC = bytes[6] << 16; + const byteD = bytes[7] * 0x1000000; + return { + magic, + version, + count: (byteA | byteB | byteC) + byteD, + }; +} export type CotarMetadata = { /** Magic string "COT" */ @@ -51,13 +63,13 @@ export class CotarIndex { if (isHeader) { await source.loadBytes(sourceOffset, source.chunkSize); const bytes = source.bytes(sourceOffset, IndexHeaderSize); - return CotarMetadataParser.read(bytes).value; + return readMetadata(bytes); } // TODO ideally this would a file inside the tar // however different tar programs seem to have differing suffixes some have "2x512" bytes of 0 others pad them out further const bytes = await source.fetchBytes(-IndexHeaderSize); - return CotarMetadataParser.read(new Uint8Array(bytes)).value; + return readMetadata(new Uint8Array(bytes)); } static async getMetadata(source: ChunkSource, sourceOffset: number, isHeader: boolean): Promise { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 9dc6490e..75a10388 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1,4 @@ export { CotarIndexBuilder, CotarIndexOptions } from './binary/binary.index.builder.js'; export { CotarIndex as CotarIndexBinary } from './binary/binary.index.js'; export { Cotar } from './cotar.js'; -export { TarHeader, TarReader } from './tar.js'; +export { TarReader } from './tar.js'; diff --git a/packages/core/src/tar.ts b/packages/core/src/tar.ts index 7db5a61f..d1b4bf80 100644 --- a/packages/core/src/tar.ts +++ b/packages/core/src/tar.ts @@ -22,7 +22,7 @@ export enum TarType { } // It takes time to load all the header in, load in only the chunks we care about -export const TarHeader = bp.object('TarHeader', { +const TarHeader = bp.static('TarHeader', { path: bp.string(100), skip1: bp.skip(24), // mode: bp.string(8),