mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-21 17:32:41 +00:00
more serialization
This commit is contained in:
@@ -57,97 +57,3 @@ export function deserializeActions(native: bigint): number[] {
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
const CHL_VERSION = 1
|
||||
const CHL_MAGIC = "CHL"
|
||||
|
||||
/**
|
||||
* Binary serialization of the chord library
|
||||
*
|
||||
* Layout is as follows:
|
||||
* ```rs
|
||||
* struct Chords {
|
||||
* magic: "CHL"
|
||||
* version: u8
|
||||
* chordCount: u32
|
||||
* chords: chord[]
|
||||
* }
|
||||
*
|
||||
* struct Chord {
|
||||
* id: u32
|
||||
* phrase: u128
|
||||
* actionCount: u16
|
||||
* actions: u8[]
|
||||
* }
|
||||
* ```
|
||||
* Serialized as little endian.
|
||||
*
|
||||
* @param chords
|
||||
*/
|
||||
export function chordsToFile(chords: Chord[]): ArrayBuffer {
|
||||
const actionsTotalCount = chords.reduce((size, chord) => size + chord.actions.length, 0)
|
||||
|
||||
const buffer = new ArrayBuffer(4 + 4 + chords.length * (4 + 16 + 2) + actionsTotalCount)
|
||||
const view = new DataView(buffer)
|
||||
let byteOffset = 0
|
||||
|
||||
for (const byte of CHL_MAGIC.split("")) {
|
||||
view.setUint8(byteOffset++, byte.codePointAt(0)!)
|
||||
}
|
||||
view.setUint8(byteOffset++, CHL_VERSION)
|
||||
view.setUint32(byteOffset, chords.length, true)
|
||||
byteOffset += 4
|
||||
for (const chord of chords) {
|
||||
const actions = serializeActions(chord.actions)
|
||||
view.setBigUint64(byteOffset, actions >> 64n, true)
|
||||
byteOffset += 8
|
||||
view.setBigUint64(byteOffset, actions & 0xffff_ffff_ffff_ffffn, true)
|
||||
byteOffset += 8
|
||||
|
||||
view.setUint16(byteOffset, chord.phrase.length, true)
|
||||
byteOffset += 2
|
||||
for (const action of chord.phrase) {
|
||||
view.setUint8(byteOffset++, action)
|
||||
}
|
||||
}
|
||||
|
||||
return buffer
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {chordsToFile}
|
||||
*/
|
||||
export function chordsFromFile(buffer: ArrayBuffer): Chord[] {
|
||||
const view = new DataView(buffer)
|
||||
let byteOffset = 0
|
||||
|
||||
const magic = []
|
||||
for (let i = 0; i < CHL_MAGIC.length; i++) {
|
||||
magic.push(view.getUint8(byteOffset++))
|
||||
}
|
||||
const magicString = String.fromCodePoint(...magic)
|
||||
if (magicString !== CHL_MAGIC) throw new Error(`Not a .chl file [magic ${magicString}]`)
|
||||
if (view.getUint8(byteOffset++) !== CHL_VERSION) throw Error("Invalid .chl [version]")
|
||||
|
||||
const chords: Chord[] = Array.from({length: view.getUint32(byteOffset, true)})
|
||||
byteOffset += 4
|
||||
for (let i = 0; i < chords.length; i++) {
|
||||
let actions = view.getBigUint64(byteOffset, true) << 64n
|
||||
byteOffset += 8
|
||||
actions |= view.getBigUint64(byteOffset, true)
|
||||
byteOffset += 8
|
||||
|
||||
const phrase: number[] = Array.from({length: view.getUint16(byteOffset, true)})
|
||||
byteOffset += 2
|
||||
for (let i = 0; i < phrase.length; i++) {
|
||||
phrase[i] = view.getUint8(byteOffset++)
|
||||
}
|
||||
|
||||
chords[i] = {
|
||||
actions: deserializeActions(actions),
|
||||
phrase,
|
||||
}
|
||||
}
|
||||
|
||||
return chords
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user