Skip to content

Commit

Permalink
feat: replace Uint8Array with ArrayBuffers
Browse files Browse the repository at this point in the history
  • Loading branch information
meszaros-lajos-gyorgy committed Dec 24, 2024
1 parent 7b78d46 commit eaf08c0
Show file tree
Hide file tree
Showing 50 changed files with 186 additions and 195 deletions.
10 changes: 5 additions & 5 deletions src/amb/AMB.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BinaryIO } from '@common/BinaryIO.js'
import { concatUint8Arrays, times } from '@common/helpers.js'
import { concatArrayBuffers, times } from '@common/helpers.js'
import { AmbHeader } from '@amb/AmbHeader.js'
import { Track, type ArxTrack } from '@amb/Track.js'

Expand All @@ -8,7 +8,7 @@ export type ArxAMB = {
}

export class AMB {
static load(decompressedFile: Uint8Array): ArxAMB {
static load(decompressedFile: ArrayBuffer): ArxAMB {
const file = new BinaryIO(decompressedFile)

const { numberOfTracks, isNewerVersion } = AmbHeader.readFrom(file)
Expand All @@ -20,10 +20,10 @@ export class AMB {
}
}

static save(json: ArxAMB): Uint8Array {
static save(json: ArxAMB): ArrayBuffer {
const header = AmbHeader.accumulateFrom(json)
const tracks = concatUint8Arrays(json.tracks.map(Track.accumulateFrom))
const tracks = concatArrayBuffers(json.tracks.map(Track.accumulateFrom))

return concatUint8Arrays([header, tracks])
return concatArrayBuffers([header, tracks])
}
}
4 changes: 2 additions & 2 deletions src/amb/AmbHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export class AmbHeader {
}
}

static accumulateFrom(json: ArxAMB): Uint8Array {
const buffer = new Uint8Array(AmbHeader.sizeOf())
static accumulateFrom(json: ArxAMB): ArrayBuffer {
const buffer = new ArrayBuffer(AmbHeader.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeString('GAMB', 4)
Expand Down
4 changes: 2 additions & 2 deletions src/amb/Key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export class Key {
}
}

static accumulateFrom(key: ArxKey): Uint8Array {
const buffer = new Uint8Array(Key.sizeOf())
static accumulateFrom(key: ArxKey): ArrayBuffer {
const buffer = new ArrayBuffer(Key.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeUint32(0) // flags
Expand Down
4 changes: 2 additions & 2 deletions src/amb/Setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class Setting {
}
}

static accumulateFrom(setting: ArxSetting): Uint8Array {
const buffer = new Uint8Array(Setting.sizeOf())
static accumulateFrom(setting: ArxSetting): ArrayBuffer {
const buffer = new ArrayBuffer(Setting.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeFloat32(setting.min)
Expand Down
8 changes: 4 additions & 4 deletions src/amb/Track.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BinaryIO } from '@common/BinaryIO.js'
import { concatUint8Arrays, times } from '@common/helpers.js'
import { concatArrayBuffers, times } from '@common/helpers.js'
import { type ArxKey, Key } from '@amb/Key.js'

/**
Expand Down Expand Up @@ -50,15 +50,15 @@ export class Track {
}
}

static accumulateFrom(track: ArxTrack): Uint8Array {
const buffer = new Uint8Array(Track.sizeOf(track))
static accumulateFrom(track: ArxTrack): ArrayBuffer {
const buffer = new ArrayBuffer(Track.sizeOf(track))
const binary = new BinaryIO(buffer)

binary.writeString(Track.toAbsolutePath(track.filename))
binary.writeString('') // name
binary.writeUint32(track.flags)
binary.writeUint32(track.keys.length)
binary.writeBuffer(concatUint8Arrays(track.keys.reverse().map(Key.accumulateFrom)))
binary.writeBuffer(concatArrayBuffers(track.keys.reverse().map(Key.accumulateFrom)))

return buffer
}
Expand Down
2 changes: 1 addition & 1 deletion src/bin/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ switch (args.from) {
}
}

let rawOut: string | Uint8Array
let rawOut: string | ArrayBuffer
switch (args.to) {
case 'json': {
rawOut = stringifyJSON(parsedIn, args.format || args.pretty || args.prettify)
Expand Down
51 changes: 30 additions & 21 deletions src/bin/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { type Buffer } from 'node:buffer'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
Expand All @@ -10,7 +11,7 @@ import {
SUPPORTED_DATA_FORMATS,
SUPPORTED_FORMATS,
} from '@bin/constants.js'
import { concatUint8Arrays } from '@common/helpers.js'
import { concatArrayBuffers } from '@common/helpers.js'

function pathToPackageJson(): string {
const filename = fileURLToPath(import.meta.url)
Expand Down Expand Up @@ -38,19 +39,16 @@ async function fileExists(filename: string): Promise<boolean> {
}
}

export async function streamToBuffer(input: NodeJS.ReadableStream): Promise<Uint8Array> {
export async function streamToBuffer(input: NodeJS.ReadableStream): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
const chunks: Uint8Array[] = []
const chunks: ArrayBuffer[] = []

// chunk is techincally a Buffer, but:
// "The Buffer class is a subclass of JavaScript's Uint8Array class and extends it"
// source: https://nodejs.org/api/buffer.html#buffer
input.on('data', (chunk: Uint8Array) => {
chunks.push(chunk)
input.on('data', (chunk: Buffer) => {
chunks.push(chunk.buffer)
})

input.on('end', () => {
resolve(concatUint8Arrays(chunks))
resolve(concatArrayBuffers(chunks))
})

input.on('error', (e: unknown) => {
Expand All @@ -76,11 +74,9 @@ export async function stringifyYAML(json: any): Promise<string> {
return YAML.stringify(json)
}

function sliceBuffer(buffer: string | Uint8Array, start?: number, end?: number): string | Uint8Array {
if (buffer instanceof Uint8Array) {
return buffer.subarray(start, end)
}

function sliceBuffer(buffer: ArrayBuffer, start: number, end?: number): ArrayBuffer
function sliceBuffer(buffer: string, start: number, end?: number): string
function sliceBuffer(buffer: string | ArrayBuffer, start: number = 0, end?: number): string | ArrayBuffer {
return buffer.slice(start, end)
}

Expand All @@ -94,15 +90,28 @@ export function quotientAndRemainder(dividend: number, divisor: number): [number
return [Math.floor(dividend / divisor), dividend % divisor]
}

export function outputInChunks(buffer: string | Uint8Array, stream: NodeJS.WritableStream, chunkSize = 1024): void {
const [numberOfWholeChunks, leftoverChunkSize] = quotientAndRemainder(chunkSize, buffer.length)
export function outputInChunks(buffer: string | ArrayBuffer, stream: NodeJS.WritableStream, chunkSize = 1024): void {
let sizeOfBuffer: number
if (typeof buffer === 'string') {
const [numberOfWholeChunks, leftoverChunkSize] = quotientAndRemainder(chunkSize, buffer.length)

for (let i = 0; i < numberOfWholeChunks; i++) {
stream.write(sliceBuffer(buffer, i * chunkSize, (i + 1) * chunkSize))
}
for (let i = 0; i < numberOfWholeChunks; i++) {
stream.write(sliceBuffer(buffer, i * chunkSize, (i + 1) * chunkSize))
}

if (leftoverChunkSize > 0) {
stream.write(sliceBuffer(buffer, numberOfWholeChunks * chunkSize))
if (leftoverChunkSize > 0) {
stream.write(sliceBuffer(buffer, numberOfWholeChunks * chunkSize))
}
} else {
const [numberOfWholeChunks, leftoverChunkSize] = quotientAndRemainder(chunkSize, buffer.byteLength)

for (let i = 0; i < numberOfWholeChunks; i++) {
stream.write(new Uint8Array(sliceBuffer(buffer, i * chunkSize, (i + 1) * chunkSize)))
}

if (leftoverChunkSize > 0) {
stream.write(new Uint8Array(sliceBuffer(buffer, numberOfWholeChunks * chunkSize)))
}
}

stream.end()
Expand Down
20 changes: 13 additions & 7 deletions src/common/BinaryIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ export class BinaryIO extends DataView {

public position: number // TODO: make this private - this needs to be public because of TEA

constructor(buffer: Uint8Array, byteOffset?: number, byteLength?: number) {
super(buffer.buffer, byteOffset, byteLength)
constructor(buffer: ArrayBuffer, byteOffset?: number, byteLength?: number) {
super(buffer, byteOffset, byteLength)
this.position = 0
}

Expand Down Expand Up @@ -244,10 +244,16 @@ export class BinaryIO extends DataView {
this.position = this.position + BinaryIO.sizeOfUint8()
}

writeUint8Array(values: number[] | Uint8Array): void {
values.forEach((value) => {
this.writeUint8(value)
})
writeUint8Array(values: number[] | ArrayBuffer): void {
if (values instanceof ArrayBuffer) {
new Uint8Array(values).forEach((value) => {
this.writeUint8(value)
})
} else {
values.forEach((value) => {
this.writeUint8(value)
})
}
}

writeUint16(value: number): void {
Expand Down Expand Up @@ -373,7 +379,7 @@ export class BinaryIO extends DataView {
this.writeFloat32Array([w, x, y, z])
}

writeBuffer(buffer: Uint8Array): void {
writeBuffer(buffer: ArrayBuffer): void {
this.writeUint8Array(buffer)
}
}
4 changes: 2 additions & 2 deletions src/common/Color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export class Color {
return { r: r * 255, g: g * 255, b: b * 255, a: 1 }
}

static accumulateFrom({ r, g, b, a }: ArxColor, mode: ColorMode): Uint8Array {
const buffer = new Uint8Array(Color.sizeOf(mode))
static accumulateFrom({ r, g, b, a }: ArxColor, mode: ColorMode): ArrayBuffer {
const buffer = new ArrayBuffer(Color.sizeOf(mode))
const binary = new BinaryIO(buffer)

if (mode === 'bgra') {
Expand Down
24 changes: 0 additions & 24 deletions src/common/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,6 @@ export function clamp(min: number, max: number, n: number): number {
return n
}

/**
* @see https://stackoverflow.com/a/49129872/1806628
* @deprecated This will be superceeded by concatArrayBuffers
*/
export function concatUint8Arrays(buffers: Uint8Array[]): Uint8Array {
if (buffers.length === 0) {
return new Uint8Array(0)
}

const totalLength = buffers.reduce((sum, buffer) => {
return sum + buffer.length
}, 0)

const combinedBuffer = new Uint8Array(totalLength)

let offset = 0
buffers.forEach((buffer) => {
combinedBuffer.set(buffer, offset)
offset = offset + buffer.length
})

return combinedBuffer
}

/**
* @see https://stackoverflow.com/a/49129872/1806628
*/
Expand Down
18 changes: 9 additions & 9 deletions src/dlf/DLF.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BinaryIO } from '@common/BinaryIO.js'
import { concatUint8Arrays, times } from '@common/helpers.js'
import { concatArrayBuffers, times } from '@common/helpers.js'
import { type ArxDlfHeader, DlfHeader } from '@dlf/DlfHeader.js'
import { type ArxFog, Fog } from '@dlf/Fog.js'
import { type ArxInteractiveObject, InteractiveObject } from '@dlf/InteactiveObject.js'
Expand Down Expand Up @@ -29,7 +29,7 @@ export type ArxDLF = {
}

export class DLF {
static load(decompressedFile: Uint8Array): ArxDLF {
static load(decompressedFile: ArrayBuffer): ArxDLF {
const file = new BinaryIO(decompressedFile)

const { numberOfInteractiveObjects, numberOfFogs, numberOfZonesAndPaths, ...header } = DlfHeader.readFrom(file)
Expand Down Expand Up @@ -90,16 +90,16 @@ export class DLF {
return data
}

static save(json: ArxDLF): Uint8Array {
static save(json: ArxDLF): ArrayBuffer {
const header = DlfHeader.accumulateFrom(json)
const scene = Scene.accumulateFrom(json.scene)
const interactiveObjects = concatUint8Arrays(json.interactiveObjects.map(InteractiveObject.accumulateFrom))
const fogs = concatUint8Arrays(json.fogs.map(Fog.accumulateFrom))
const interactiveObjects = concatArrayBuffers(json.interactiveObjects.map(InteractiveObject.accumulateFrom))
const fogs = concatArrayBuffers(json.fogs.map(Fog.accumulateFrom))
const numberOfNodes = 0
const numberOfNodeLinks = 12
const nodes = new Uint8Array(numberOfNodes * (204 + numberOfNodeLinks * 64))
const nodes = new ArrayBuffer(numberOfNodes * (204 + numberOfNodeLinks * 64))

const paths = concatUint8Arrays(
const paths = concatArrayBuffers(
json.paths.flatMap((path) => {
const header = ZoneAndPathHeader.allocateFrom(path)
const { pos } = path.points[0]
Expand All @@ -111,7 +111,7 @@ export class DLF {
}),
)

const zones = concatUint8Arrays(
const zones = concatArrayBuffers(
json.zones.flatMap((zone) => {
const header = ZoneAndPathHeader.allocateFrom(zone)
const { pos } = zone.points[0]
Expand All @@ -123,6 +123,6 @@ export class DLF {
}),
)

return concatUint8Arrays([header, scene, interactiveObjects, fogs, nodes, paths, zones])
return concatArrayBuffers([header, scene, interactiveObjects, fogs, nodes, paths, zones])
}
}
4 changes: 2 additions & 2 deletions src/dlf/DlfHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export class DlfHeader {
}
}

static accumulateFrom(json: ArxDLF): Uint8Array {
const buffer = new Uint8Array(DlfHeader.sizeOf())
static accumulateFrom(json: ArxDLF): ArrayBuffer {
const buffer = new ArrayBuffer(DlfHeader.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeFloat32(DANAE_VERSION)
Expand Down
4 changes: 2 additions & 2 deletions src/dlf/Fog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ export class Fog {
}
}

static accumulateFrom(fog: ArxFog): Uint8Array {
const buffer = new Uint8Array(Fog.sizeOf())
static accumulateFrom(fog: ArxFog): ArrayBuffer {
const buffer = new ArrayBuffer(Fog.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeVector3(fog.pos)
Expand Down
4 changes: 2 additions & 2 deletions src/dlf/InteactiveObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export class InteractiveObject {
return data
}

static accumulateFrom(interactiveObject: ArxInteractiveObject): Uint8Array {
const buffer = new Uint8Array(InteractiveObject.sizeOf())
static accumulateFrom(interactiveObject: ArxInteractiveObject): ArrayBuffer {
const buffer = new ArrayBuffer(InteractiveObject.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeString(InteractiveObject.toAbsolutePath(interactiveObject.name), 512)
Expand Down
4 changes: 2 additions & 2 deletions src/dlf/Scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export class Scene {
}
}

static accumulateFrom(scene: ArxScene): Uint8Array {
const buffer = new Uint8Array(Scene.sizeOf())
static accumulateFrom(scene: ArxScene): ArrayBuffer {
const buffer = new ArrayBuffer(Scene.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeString(Scene.levelIdxToPath(scene.levelIdx), 512)
Expand Down
4 changes: 2 additions & 2 deletions src/dlf/ZoneAndPathPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export class ZoneAndPathPoint {
return data
}

static allocateFrom(point: ArxZoneAndPathPoint, pos: ArxVector3): Uint8Array {
const buffer = new Uint8Array(ZoneAndPathPoint.sizeOf())
static allocateFrom(point: ArxZoneAndPathPoint, pos: ArxVector3): ArrayBuffer {
const buffer = new ArrayBuffer(ZoneAndPathPoint.sizeOf())
const binary = new BinaryIO(buffer)

const rpos = {
Expand Down
4 changes: 2 additions & 2 deletions src/ftl/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export class Action {
}
}

static accumulateFrom(action: ArxAction): Uint8Array {
const buffer = new Uint8Array(Action.sizeOf())
static accumulateFrom(action: ArxAction): ArrayBuffer {
const buffer = new ArrayBuffer(Action.sizeOf())
const binary = new BinaryIO(buffer)

binary.writeString(action.name, 256)
Expand Down
Loading

0 comments on commit eaf08c0

Please sign in to comment.