Files
risuai/src/ts/storage/risuSave.ts

90 lines
2.7 KiB
TypeScript

import { Packr, Unpackr, decode } from "msgpackr";
import * as fflate from "fflate";
import { isTauri } from "../globalApi";
const packr = new Packr({
useRecords:false
});
const unpackr = new Unpackr({
int64AsType: 'number',
useRecords:false
})
const magicHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 7]);
const magicCompressedHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 8]);
export function encodeRisuSaveLegacy(data:any, compression:'noCompression'|'compression' = 'noCompression'){
let encoded:Uint8Array = packr.encode(data)
if(compression === 'compression'){
encoded = fflate.compressSync(encoded)
const result = new Uint8Array(encoded.length + magicCompressedHeader.length);
result.set(magicCompressedHeader, 0)
result.set(encoded, magicCompressedHeader.length)
return result
}
else{
const result = new Uint8Array(encoded.length + magicHeader.length);
result.set(magicHeader, 0)
result.set(encoded, magicHeader.length)
return result
}
}
export function decodeRisuSave(data:Uint8Array){
try {
switch(checkHeader(data)){
case "compressed":
data = data.slice(magicCompressedHeader.length)
return decode(fflate.decompressSync(data))
case "raw":
data = data.slice(magicHeader.length)
return unpackr.decode(data)
}
return unpackr.decode(data)
}
catch (error) {
try {
console.log('risudecode')
const risuSaveHeader = new Uint8Array(Buffer.from("\u0000\u0000RISU",'utf-8'))
const realData = data.subarray(risuSaveHeader.length)
const dec = unpackr.decode(realData)
return dec
} catch (error) {
const buf = Buffer.from(fflate.decompressSync(Buffer.from(data)))
try {
return JSON.parse(buf.toString('utf-8'))
} catch (error) {
return unpackr.decode(buf)
}
}
}
}
function checkHeader(data: Uint8Array) {
let header:'none'|'compressed'|'raw' = 'raw'
if (data.length < magicHeader.length) {
return false;
}
for (let i = 0; i < magicHeader.length; i++) {
if (data[i] !== magicHeader[i]) {
header = 'none'
break
}
}
if(header === 'none'){
header = 'compressed'
for (let i = 0; i < magicCompressedHeader.length; i++) {
if (data[i] !== magicCompressedHeader[i]) {
header = 'none'
break
}
}
}
// All bytes matched
return header;
}