Skip to content

Commit

Permalink
feat: implement binary meta
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Oct 4, 2024
1 parent f31856e commit d016a56
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 9 deletions.
77 changes: 77 additions & 0 deletions utils/lt-code/binary-meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Merge multiple Uint8Array into a single Uint8Array
* Each chunk is prefixed with a 4-byte Uint32 to store the length of the chunk
*/
export function mergeUint8Arrays(arrays: Uint8Array[]) {
const totalLength = arrays.reduce((sum, arr) => sum + arr.length + 4, 0) // 4 是為了存每個數組的長度 (Uint32)

const mergedArray = new Uint8Array(totalLength)
let offset = 0

arrays.forEach((arr) => {
const length = arr.length
// 將長度存成 4 bytes 的 Uint32
mergedArray[offset++] = (length >> 24) & 0xFF
mergedArray[offset++] = (length >> 16) & 0xFF
mergedArray[offset++] = (length >> 8) & 0xFF
mergedArray[offset++] = length & 0xFF

// 複製 Uint8Array 到合併數組中
mergedArray.set(arr, offset)
offset += length
})

return mergedArray
}

/**
* Split a merged Uint8Array into multiple Uint8Array
*/
export function splitUint8Arrays(mergedArray: Uint8Array): Uint8Array[] {
const arrays = []
let offset = 0

while (offset < mergedArray.length) {
// 讀取 Uint8Array 的長度 (從 4 bytes)
const length = (mergedArray[offset++]! << 24)
| (mergedArray[offset++]! << 16)
| (mergedArray[offset++]! << 8)
| mergedArray[offset++]!

// 根據長度切割出原始 Uint8Array
const arr = mergedArray.slice(offset, offset + length)
arrays.push(arr)
offset += length
}

return arrays
}

export function appendMetaToBuffer<T>(data: Uint8Array, meta: T): Uint8Array {
const json = JSON.stringify(meta)
const metaBuffer = stringToUint8Array(json)
return mergeUint8Arrays([metaBuffer, data])
}

export function readMetaFromBuffer<T>(buffer: Uint8Array): [data: Uint8Array, meta: T] {
const splitted = splitUint8Arrays(buffer) as [Uint8Array, Uint8Array]
if (splitted.length !== 2) {
throw new Error('Invalid buffer')
}
const [metaBuffer, data] = splitted
const meta = JSON.parse(uint8ArrayToString(metaBuffer!))
return [data, meta]
}

export function stringToUint8Array(str: string): Uint8Array {
const data = new Uint8Array(str.length)
for (let i = 0; i < str.length; i++) {
data[i] = str.charCodeAt(i)
}

return data
}

export function uint8ArrayToString(data: Uint8Array): string {
return String.fromCharCode(...data)
}
9 changes: 0 additions & 9 deletions utils/lt-code/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,6 @@ export function xorUint8Array(a: Uint8Array, b: Uint8Array): Uint8Array {
return result
}

export function stringToUint8Array(str: string): Uint8Array {
const data = new Uint8Array(str.length)
for (let i = 0; i < str.length; i++) {
data[i] = str.charCodeAt(i)
}

return data
}

/**
* Convert Content-Type string to @see ContentType enum.
*
Expand Down

0 comments on commit d016a56

Please sign in to comment.