serde-ts/src/registry.ts

113 lines
3.4 KiB
TypeScript

import { Deserialize, IDeserializer, IIterableAccess, IMapAccess } from './de'
import { ISerializer, Serialize } from './ser'
import { isObject, Null, PrimitivePrototype, type } from './utils'
export class Registry {
serializers: Map<Function, Serialize<any, any>> = new Map()
deserializers: Map<Function, Deserialize<any>> = new Map()
registerSerialize<T, U>(ctor: Function, serialize: Serialize<T, U>) {
this.serializers.set(ctor, serialize)
}
registerDeserialize<T>(ctor: Function, deserialize: Deserialize<T>) {
this.deserializers.set(ctor, deserialize)
}
}
export const GlobalRegistry = new Registry()
export const registerSerialize = GlobalRegistry.registerSerialize.bind(GlobalRegistry)
export const registerDeserialize = GlobalRegistry.registerDeserialize.bind(GlobalRegistry)
function getFrom<T, V>(map: Map<Function, T>, value: V): T {
return map.get(type(value)) as T
}
export function getSerialize<T, U>(value: U, fallback: Serialize<T, U>, registry: Registry): Serialize<T, U> {
return getFrom(registry.serializers, value) || fallback
}
export function getDeserialize<T, U>(value: U, fallback: Deserialize<T>, registry: Registry): Deserialize<T> {
return getFrom(registry.deserializers, value) || fallback
}
registerSerialize(Boolean, <T, U>(ser: ISerializer<T>, value: U) => ser.serializeBoolean(value as boolean))
registerSerialize(String, <T, U>(ser: ISerializer<T>, value: U) => ser.serializeString(value as string))
registerSerialize(Number, <T, U>(ser: ISerializer<T>, value: U) => ser.serializeNumber(value as number))
registerSerialize(BigInt, <T, U>(ser: ISerializer<T>, value: U) => ser.serializeBigInt(value as bigint))
registerSerialize(Symbol, <T, U>(ser: ISerializer<T>, value: U) => ser.serializeSymbol(value as symbol))
registerSerialize(Null, <T, U>(ser: ISerializer<T>, _value: U) => ser.serializeNull())
registerSerialize(Object, <T, U>(ser: ISerializer<T>, value: U) => {
const obj = Object.entries(value as object)
const serObj = ser.serializeObject(obj.length)
obj.forEach(([key, value]) => serObj.serializeEntry(key, value))
return serObj.end()
})
registerSerialize(Array, <T, U>(ser: ISerializer<T>, value: U) => {
const arr = value as any[]
const iter = ser.serializeIterable(arr.length)
arr.forEach((value: any) => iter.serializeElement(value))
return iter.end()
})
registerDeserialize(Boolean, (de: IDeserializer) => de.deserializeBoolean({
visitBoolean(value: boolean) {
return value
}
}))
registerDeserialize(String, (de: IDeserializer) => de.deserializeString({
visitString(value: string) {
return value
}
}))
registerDeserialize(Number, (de: IDeserializer) => de.deserializeNumber({
visitNumber(value: number) {
return value
}
}))
registerDeserialize(BigInt, (de: IDeserializer) => de.deserializeBigInt({
visitBigInt(value: bigint) {
return value
}
}))
registerDeserialize(Symbol, (de: IDeserializer) => de.deserializeSymbol({
visitSymbol(value: symbol) {
return value
}
}))
registerDeserialize(Object, (de: IDeserializer) => de.deserializeObject({
visitObject(access: IMapAccess) {
let result = {} as any
for (const [key, value] of access) {
result[key] = value
}
return result
}
}))
registerDeserialize(Array, (de: IDeserializer) => de.deserializeIterable({
visitIterable(access: IIterableAccess) {
let result = []
for (const value of access) {
result.push(value)
}
return result
}
}))