resolve stuff

This commit is contained in:
Rowan 2025-05-18 03:01:11 -05:00
parent dec78265a3
commit aae64081ad
8 changed files with 59 additions and 16 deletions

View file

@ -61,3 +61,4 @@ export function convertCase(value: string, convention: CaseConvention) {
return joinMap(upper, '-', words) return joinMap(upper, '-', words)
} }
} }

View file

@ -48,7 +48,7 @@ export class GenericVisitor<T> implements Visitor<T> {
return result return result
} }
visitIterable?(access: IterableAccess): T { visitIterable(access: IterableAccess): T {
const result = new Array(access.sizeHint()) const result = new Array(access.sizeHint())
let element let element

View file

@ -74,7 +74,8 @@ export interface Deserializer {
deserializeSymbol<T, V extends Visitor<T>>(visitor: V): T deserializeSymbol<T, V extends Visitor<T>>(visitor: V): T
deserializeNull<T, V extends Visitor<T>>(visitor: V): T deserializeNull<T, V extends Visitor<T>>(visitor: V): T
deserializeObject<T, V extends Visitor<T>>(visitor: V): T deserializeObject<T, V extends Visitor<T>>(visitor: V): T
deserializeIterable?<T, V extends Visitor<T>>(visitor: V): T deserializeClass<T, V extends Visitor<T>>(name: string, fields: string[], visitor: V): T
deserializeIterable<T, V extends Visitor<T>>(visitor: V): T
} }
export interface Deserialize<T> { export interface Deserialize<T> {

View file

@ -1,4 +1,5 @@
import { ContainerOptions, PropertyOptions, SerdeOptions } from './options' import { ContainerOptions, PropertyOptions, SerdeOptions } from './options'
import { GlobalRegistry, Registry } from './registry'
export const Serde = Symbol('Serde') export const Serde = Symbol('Serde')
@ -42,3 +43,10 @@ export function serde(options: ContainerOptions | PropertyOptions) {
export function getMetadata(value: any) { export function getMetadata(value: any) {
return value[Serde] return value[Serde]
} }
export function register(registry: Registry = GlobalRegistry) {
return function(target: any) {
registry.add(target)
return target
}
}

View file

@ -1,4 +1,5 @@
import { DefaultIterableAccessImpl, DefaultMapAccessImpl, Deserialize, Deserializer, IterableAccess, MapAccess, Visitor } from './de' import { DefaultIterableAccessImpl, DefaultMapAccessImpl, Deserialize, Deserializer, IterableAccess, MapAccess, Visitor } from './de'
import { GlobalRegistry, Registry } from './registry'
import { IterableSerializer, ObjectSerializer, Serializable, Serializer, serializeWith } from './ser' import { IterableSerializer, ObjectSerializer, Serializable, Serializer, serializeWith } from './ser'
import { mixin, Nullable } from './utils' import { mixin, Nullable } from './utils'
@ -328,10 +329,12 @@ export class JSONSerializer implements Serializer<void> {
const unexpected = (expected: string, actual: string, position: number) => new SyntaxError(`Expected ${expected} at position ${position} (got '${actual}')`) const unexpected = (expected: string, actual: string, position: number) => new SyntaxError(`Expected ${expected} at position ${position} (got '${actual}')`)
export class JSONDeserializer implements Deserializer { export class JSONDeserializer implements Deserializer {
private readonly registry: Registry
readonly buffer: StringBuffer readonly buffer: StringBuffer
constructor(buffer: StringBuffer) { constructor(buffer: StringBuffer, registry: Registry = GlobalRegistry) {
this.buffer = buffer this.buffer = buffer
this.registry = registry
} }
static fromString(value: string): JSONDeserializer { static fromString(value: string): JSONDeserializer {
@ -353,7 +356,7 @@ export class JSONDeserializer implements Deserializer {
case Token.Quote === byte: case Token.Quote === byte:
return this.deserializeString(visitor) return this.deserializeString(visitor)
case Token.LeftSquare === byte: case Token.LeftSquare === byte:
return this.deserializeIterable!(visitor) return this.deserializeIterable(visitor)
case Token.LeftCurly === byte: case Token.LeftCurly === byte:
return this.deserializeObject(visitor) return this.deserializeObject(visitor)
default: default:
@ -386,6 +389,14 @@ export class JSONDeserializer implements Deserializer {
} }
} }
deserializeClass<T, V extends Visitor<T>>(name: string, fields: string[], visitor: V): T {
const cls = this.registry.get(name)
// TODO: deserialize name representing class name, use the existing deserializeWith logic
// to deserialize the class here. likely, deserialize name and then return a CommaSeparated
// object
}
deserializeString<T, V extends Visitor<T>>(visitor: V): T { deserializeString<T, V extends Visitor<T>>(visitor: V): T {
const next = this.buffer.take() const next = this.buffer.take()
if (next.next() === Token.Quote) { if (next.next() === Token.Quote) {
@ -449,7 +460,7 @@ export class JSONDeserializer implements Deserializer {
throw new Error('Method not implemented.') throw new Error('Method not implemented.')
} }
deserializeIterable?<T, V extends Visitor<T>>(visitor: V): T { deserializeIterable<T, V extends Visitor<T>>(visitor: V): T {
let next = this.buffer.take() let next = this.buffer.take()
if (next.next() === Token.LeftSquare) { if (next.next() === Token.LeftSquare) {

View file

@ -2,6 +2,7 @@ import { CaseConvention, convertCase } from './case'
import { Deserializer } from './de' import { Deserializer } from './de'
import { Serializer } from './ser' import { Serializer } from './ser'
import { isFunction, isNumber, isString } from './utils' import { isFunction, isNumber, isString } from './utils'
import { GlobalRegistry, Registry } from './registry'
export interface RenameOptions { export interface RenameOptions {
@ -17,14 +18,15 @@ export interface RenameAllOptions {
export interface ContainerOptions { export interface ContainerOptions {
// deserialization only // deserialization only
default?: () => any default?: () => any
rename?: RenameOptions | string
renameAll?: RenameAllOptions | CaseConvention
// deserialization only // deserialization only
denyUnknownFields?: boolean denyUnknownFields?: boolean
expecting?: string
rename?: RenameOptions | string
renameAll?: RenameAllOptions | CaseConvention
registry?: Registry
tag?: string tag?: string
content?: string content?: string
untagged?: boolean untagged?: boolean
expecting?: string
} }
export interface ConditionalSkipOptions { export interface ConditionalSkipOptions {
@ -59,8 +61,12 @@ export type Stage = typeof Stage[keyof typeof Stage]
export class SerdeOptions { export class SerdeOptions {
private readonly target: any private readonly target: any
options: ContainerOptions readonly options: ContainerOptions
properties: Map<string, PropertyOptions> readonly properties: Map<string, PropertyOptions>
get registry() {
return this.options.registry || GlobalRegistry
}
constructor(target: any, options: ContainerOptions = {}, properties: Map<string, PropertyOptions> = new Map()) { constructor(target: any, options: ContainerOptions = {}, properties: Map<string, PropertyOptions> = new Map()) {
this.target = target this.target = target

16
src/registry.ts Normal file
View file

@ -0,0 +1,16 @@
import { Constructor } from './utils'
export class Registry {
registeredClasses: Map<string, Constructor> = new Map()
add(ctor: Constructor, key: string = ctor.name) {
this.registeredClasses.set(key, ctor)
}
get(name: string) {
return this.registeredClasses.get(name)
}
}
export const GlobalRegistry = new Registry()

View file

@ -11,10 +11,10 @@ export interface IterableSerializer<T = void> {
end(): T end(): T
} }
//export interface ClassSerializer<T = void> { export interface ClassSerializer<T = void> {
// serializeField<U extends Serializable>(name: PropertyKey, value: U): T serializeField<U extends Serializable>(name: PropertyKey, value: U): T
// end(): T end(): T
//} }
const TypeSerializerMethods = [ const TypeSerializerMethods = [
'serializeString', 'serializeString',
@ -26,7 +26,7 @@ const TypeSerializerMethods = [
'serializeIterable', 'serializeIterable',
'serializeNull', 'serializeNull',
'serializeObject', 'serializeObject',
//'serializeInstance', 'serializeClass',
] as const ] as const
interface TypeSerializer<T> { interface TypeSerializer<T> {
@ -39,7 +39,7 @@ interface TypeSerializer<T> {
serializeObject(): ObjectSerializer<T> serializeObject(): ObjectSerializer<T>
// serializeMap?(): ObjectSerializer<T> // serializeMap?(): ObjectSerializer<T>
serializeIterable?(): IterableSerializer<T> serializeIterable?(): IterableSerializer<T>
//serializeClass?(name: PropertyKey): ClassSerializer<T> serializeClass(name: PropertyKey): ClassSerializer<T>
} }
const AnySerializerMethods = ['serializeAny'] const AnySerializerMethods = ['serializeAny']