113 lines
3.4 KiB
TypeScript
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
|
|
}
|
|
}))
|