wip classes

This commit is contained in:
Rowan 2025-05-20 02:25:09 -05:00
parent 69e56d2d74
commit 5ef148193e
14 changed files with 47 additions and 10 deletions

View file

@ -11,5 +11,6 @@ export declare class GenericVisitor<T> implements Visitor<T> {
visitSymbol(value: symbol): T;
visitNull(): T;
visitObject(access: MapAccess): T;
visitClass(name: string, value: MapAccess): T;
visitIterable(access: IterableAccess): T;
}

4
dist/de/generic.js vendored
View file

@ -91,6 +91,10 @@ class GenericVisitor {
}
return result;
}
visitClass(name, value) {
console.log(name, '!!!!!!');
return this.visitObject(value);
}
visitIterable(access) {
const result = new Array(access.sizeHint());
let element;

2
dist/de/impl.js vendored
View file

@ -6,7 +6,7 @@ const generic_1 = require("./generic");
function deserializeWith(deserializer, into, options) {
const visitor = new generic_1.GenericVisitor();
const target = new into();
const obj = deserializer.deserializeObject(visitor);
const obj = deserializer.deserializeClass(into.name, visitor);
const newObject = {};
for (const property in target) {
const name = options.getPropertyName(property, options_1.Stage.Deserialize);

View file

@ -33,6 +33,7 @@ export interface Visitor<T> {
visitSymbol(value: symbol): T;
visitNull(): T;
visitObject(value: MapAccess): T;
visitClass(name: string, value: MapAccess): T;
visitIterable?(value: IterableAccess): T;
}
export interface Deserializer {
@ -44,6 +45,7 @@ export interface Deserializer {
deserializeSymbol<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;
deserializeClass<T, V extends Visitor<T>>(name: string, visitor: V): T;
deserializeIterable<T, V extends Visitor<T>>(visitor: V): T;
}
export interface Deserialize<T> {

2
dist/options.d.ts vendored
View file

@ -31,7 +31,7 @@ export interface SkipOptions {
export type CustomSerializer = <T, V, S extends Serializer<T>>(value: V, serializer: S) => T;
export type CustomDeserializer = <T, D extends Deserializer>(deserializer: D) => T;
export interface PropertyOptions {
alias?: string;
aliases?: Set<string>;
default?: () => any;
flatten?: boolean;
rename?: RenameOptions | string;

10
dist/ser/impl.js vendored
View file

@ -17,8 +17,13 @@ function serializeEntries(serializer, value, options) {
}
return serializer.end();
}
function serializeClass(serializer, value, options) {
const ser = serializer.serializeClass(value.constructor.name);
return serializeEntries(ser, Object.entries(value), options);
}
function serializeObject(serializer, value, options) {
return serializeEntries(serializer.serializeObject(), Object.entries(value), options);
const ser = serializer.serializeObject();
return serializeEntries(ser, Object.entries(value), options);
}
function serializeIter(serializer, value, options) {
let state;
@ -47,6 +52,9 @@ function serializeWith(serializer, value, optionsGetter = defaultOptions) {
if ((0, utils_1.isIterable)(value) && (0, utils_1.isFunction)(serializer.serializeIterable)) {
return serializeIter(serializer.serializeIterable(), value, options);
}
else if (!(0, utils_1.isPlainObject)(value)) {
return serializeClass(serializer, value, options);
}
else if ((0, utils_1.isFunction)(serializer.serializeObject)) {
return serializeObject(serializer, value, options);
} // deliberate fallthrough when the above fail

View file

@ -17,6 +17,7 @@ interface TypeSerializer<T> {
serializeNull(): T;
serializeObject(): ObjectSerializer<T>;
serializeIterable?(): IterableSerializer<T>;
serializeClass(name: PropertyKey): ObjectSerializer<T>;
}
interface AnySerializer<T> {
serializeAny?(value?: any): T;

View file

@ -12,7 +12,7 @@ const TypeSerializerMethods = [
'serializeIterable',
'serializeNull',
'serializeObject',
//'serializeClass',
'serializeClass',
];
const AnySerializerMethods = ['serializeAny'];
function isGenericSerializer(value) {

View file

@ -48,6 +48,12 @@ export class GenericVisitor<T> implements Visitor<T> {
return result
}
// TODO: use global registry to deserialize classes
visitClass(name: string, access: MapAccess): T {
console.log(name, '!!!!!!')
return this.visitObject(access)
}
visitIterable(access: IterableAccess): T {
const result = new Array(access.sizeHint())
let element

View file

@ -6,8 +6,12 @@ type DeserializeConstructor<T> = Deserialize<T> & { new(): Deserialize<T> }
export function deserializeWith<T, D extends Deserializer, E extends DeserializeConstructor<T>>(deserializer: D, into: E, options: SerdeOptions): T {
const visitor = new GenericVisitor<T>()
// options to figure out properties/fields during deserialization:
// offer schema decorator
// parse fields from javascript with acorn
// allow no-param constructor for initialization - this is what it does now
const target = new into()
const obj = deserializer.deserializeObject(visitor) as any
const obj = deserializer.deserializeClass(into.name, visitor) as any
const newObject = {} as any
for (const property in target) {

View file

@ -62,6 +62,7 @@ export interface Visitor<T> {
visitSymbol(value: symbol): T
visitNull(): T
visitObject(value: MapAccess): T
visitClass(name: string, value: MapAccess): T
visitIterable?(value: IterableAccess): T
}
@ -74,6 +75,7 @@ export interface Deserializer {
deserializeSymbol<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
deserializeClass<T, V extends Visitor<T>>(name: string, visitor: V): T
deserializeIterable<T, V extends Visitor<T>>(visitor: V): T
}

View file

@ -42,7 +42,7 @@ export type CustomSerializer = <T, V, S extends Serializer<T>>(value: V, seriali
export type CustomDeserializer = <T, D extends Deserializer>(deserializer: D) => T
export interface PropertyOptions {
alias?: string
aliases?: Set<string>
// deserialization only
default?: () => any
flatten?: boolean

View file

@ -1,6 +1,6 @@
import { IterableSerializer, ObjectSerializer, Serializable, Serializer } from './interface'
import { SerdeOptions, Stage } from '../options'
import { ifNull, isFunction, isIterable, Nullable, orElse } from '../utils'
import { ifNull, isFunction, isIterable, isPlainObject, Nullable, orElse } from '../utils'
const unhandledType = (serializer: any, value: any) => new TypeError(`'${serializer.constructor.name}' has no method for value type '${typeof value}'`)
@ -20,8 +20,15 @@ function serializeEntries<T, K extends string, V extends Serializable, E extends
return serializer.end()
}
function serializeClass<T, K extends string, V extends Serializable, R extends Record<K, V>>(serializer: Serializer<T>, value: R, options?: SerdeOptions) {
const ser = serializer.serializeClass!(value.constructor.name)
return serializeEntries(ser, Object.entries(value) as Iterable<[K, V]>, options)
}
function serializeObject<T, K extends string, V extends Serializable, R extends Record<K, V>>(serializer: Serializer<T>, value: R, options?: SerdeOptions) {
return serializeEntries(serializer.serializeObject!(), Object.entries(value) as Iterable<[K, V]>, options)
const ser = serializer.serializeObject!()
return serializeEntries(ser, Object.entries(value) as Iterable<[K, V]>, options)
}
function serializeIter<T, V extends Iterable<any>>(serializer: IterableSerializer<T>, value: V, options?: SerdeOptions) {
@ -61,6 +68,8 @@ export function serializeWith<T>(serializer: Serializer<T>, value: Serializable,
const options = optionsGetter(value)
if (isIterable(value) && isFunction(serializer.serializeIterable)) {
return serializeIter(serializer.serializeIterable(), value, options)
} else if (!isPlainObject(value)) {
return serializeClass(serializer, value as Record<PropertyKey, any>, options)
} else if (isFunction(serializer.serializeObject)) {
return serializeObject(serializer, value as Record<PropertyKey, any>, options)
} // deliberate fallthrough when the above fail

View file

@ -21,7 +21,7 @@ const TypeSerializerMethods = [
'serializeIterable',
'serializeNull',
'serializeObject',
//'serializeClass',
'serializeClass',
] as const
interface TypeSerializer<T> {
@ -34,7 +34,7 @@ interface TypeSerializer<T> {
serializeObject(): ObjectSerializer<T>
// serializeMap?(): ObjectSerializer<T>
serializeIterable?(): IterableSerializer<T>
//serializeClass(name: PropertyKey): ObjectSerializer<T>
serializeClass(name: PropertyKey): ObjectSerializer<T>
}
const AnySerializerMethods = ['serializeAny']