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; visitSymbol(value: symbol): T;
visitNull(): T; visitNull(): T;
visitObject(access: MapAccess): T; visitObject(access: MapAccess): T;
visitClass(name: string, value: MapAccess): T;
visitIterable(access: IterableAccess): T; visitIterable(access: IterableAccess): T;
} }

4
dist/de/generic.js vendored
View file

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

2
dist/de/impl.js vendored
View file

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

View file

@ -33,6 +33,7 @@ export interface Visitor<T> {
visitSymbol(value: symbol): T; visitSymbol(value: symbol): T;
visitNull(): T; visitNull(): T;
visitObject(value: MapAccess): T; visitObject(value: MapAccess): T;
visitClass(name: string, value: MapAccess): T;
visitIterable?(value: IterableAccess): T; visitIterable?(value: IterableAccess): T;
} }
export interface Deserializer { export interface Deserializer {
@ -44,6 +45,7 @@ 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;
deserializeClass<T, V extends Visitor<T>>(name: string, visitor: V): T;
deserializeIterable<T, V extends Visitor<T>>(visitor: V): T; deserializeIterable<T, V extends Visitor<T>>(visitor: V): T;
} }
export interface Deserialize<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 CustomSerializer = <T, V, S extends Serializer<T>>(value: V, serializer: S) => T;
export type CustomDeserializer = <T, D extends Deserializer>(deserializer: D) => T; export type CustomDeserializer = <T, D extends Deserializer>(deserializer: D) => T;
export interface PropertyOptions { export interface PropertyOptions {
alias?: string; aliases?: Set<string>;
default?: () => any; default?: () => any;
flatten?: boolean; flatten?: boolean;
rename?: RenameOptions | string; rename?: RenameOptions | string;

10
dist/ser/impl.js vendored
View file

@ -17,8 +17,13 @@ function serializeEntries(serializer, value, options) {
} }
return serializer.end(); 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) { 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) { function serializeIter(serializer, value, options) {
let state; let state;
@ -47,6 +52,9 @@ function serializeWith(serializer, value, optionsGetter = defaultOptions) {
if ((0, utils_1.isIterable)(value) && (0, utils_1.isFunction)(serializer.serializeIterable)) { if ((0, utils_1.isIterable)(value) && (0, utils_1.isFunction)(serializer.serializeIterable)) {
return serializeIter(serializer.serializeIterable(), value, options); 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)) { else if ((0, utils_1.isFunction)(serializer.serializeObject)) {
return serializeObject(serializer, value, options); return serializeObject(serializer, value, options);
} // deliberate fallthrough when the above fail } // deliberate fallthrough when the above fail

View file

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

View file

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

View file

@ -48,6 +48,12 @@ export class GenericVisitor<T> implements Visitor<T> {
return result 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 { visitIterable(access: IterableAccess): T {
const result = new Array(access.sizeHint()) const result = new Array(access.sizeHint())
let element 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 { export function deserializeWith<T, D extends Deserializer, E extends DeserializeConstructor<T>>(deserializer: D, into: E, options: SerdeOptions): T {
const visitor = new GenericVisitor<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 target = new into()
const obj = deserializer.deserializeObject(visitor) as any const obj = deserializer.deserializeClass(into.name, visitor) as any
const newObject = {} as any const newObject = {} as any
for (const property in target) { for (const property in target) {

View file

@ -62,6 +62,7 @@ export interface Visitor<T> {
visitSymbol(value: symbol): T visitSymbol(value: symbol): T
visitNull(): T visitNull(): T
visitObject(value: MapAccess): T visitObject(value: MapAccess): T
visitClass(name: string, value: MapAccess): T
visitIterable?(value: IterableAccess): T visitIterable?(value: IterableAccess): T
} }
@ -74,6 +75,7 @@ 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
deserializeClass<T, V extends Visitor<T>>(name: string, visitor: V): T
deserializeIterable<T, V extends Visitor<T>>(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 type CustomDeserializer = <T, D extends Deserializer>(deserializer: D) => T
export interface PropertyOptions { export interface PropertyOptions {
alias?: string aliases?: Set<string>
// deserialization only // deserialization only
default?: () => any default?: () => any
flatten?: boolean flatten?: boolean

View file

@ -1,6 +1,6 @@
import { IterableSerializer, ObjectSerializer, Serializable, Serializer } from './interface' import { IterableSerializer, ObjectSerializer, Serializable, Serializer } from './interface'
import { SerdeOptions, Stage } from '../options' 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}'`) 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() 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) { 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) { 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) const options = optionsGetter(value)
if (isIterable(value) && isFunction(serializer.serializeIterable)) { if (isIterable(value) && isFunction(serializer.serializeIterable)) {
return serializeIter(serializer.serializeIterable(), value, options) return serializeIter(serializer.serializeIterable(), value, options)
} else if (!isPlainObject(value)) {
return serializeClass(serializer, value as Record<PropertyKey, any>, options)
} else if (isFunction(serializer.serializeObject)) { } else if (isFunction(serializer.serializeObject)) {
return serializeObject(serializer, value as Record<PropertyKey, any>, options) return serializeObject(serializer, value as Record<PropertyKey, any>, options)
} // deliberate fallthrough when the above fail } // deliberate fallthrough when the above fail

View file

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