prepare to add options
This commit is contained in:
parent
a163468b7f
commit
da1fad1cd0
36 changed files with 1262 additions and 805 deletions
34
dist/de/forward.d.ts
vendored
Normal file
34
dist/de/forward.d.ts
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { Deserialize, IDeserializer, IterableAccess, IVisitor, MapAccess } from './interface';
|
||||
export declare class ForwardMapAccess extends MapAccess {
|
||||
private readonly keys;
|
||||
private readonly values;
|
||||
private kindex;
|
||||
private vindex;
|
||||
constructor(keys: string[], values: any[]);
|
||||
static fromObject(obj: object): ForwardMapAccess;
|
||||
nextKeySeed<T, K extends Deserialize>(_seed: K): IteratorResult<T>;
|
||||
nextValueSeed<T, V extends Deserialize>(_seed: V): IteratorResult<T>;
|
||||
nextKey<T>(): IteratorResult<T>;
|
||||
nextValue<V>(): IteratorResult<V>;
|
||||
}
|
||||
export declare class ForwardIterableAccess extends IterableAccess {
|
||||
private readonly items;
|
||||
private index;
|
||||
constructor(items: any[]);
|
||||
nextElement<T>(): IteratorResult<T>;
|
||||
}
|
||||
export declare class Forward implements IDeserializer {
|
||||
private readonly value;
|
||||
constructor(value: any);
|
||||
static with(value: any): Forward;
|
||||
deserializeAny<T, V extends IVisitor<T>>(_visitor: V): T;
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeFunction<T, V extends IVisitor<T>>(_visitor: V): T;
|
||||
}
|
134
dist/de/forward.js
vendored
Normal file
134
dist/de/forward.js
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Forward = exports.ForwardIterableAccess = exports.ForwardMapAccess = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
const interface_1 = require("./interface");
|
||||
class ForwardMapAccess extends interface_1.MapAccess {
|
||||
constructor(keys, values) {
|
||||
super();
|
||||
Object.defineProperty(this, "keys", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "values", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "kindex", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
Object.defineProperty(this, "vindex", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
this.keys = keys;
|
||||
this.values = values;
|
||||
}
|
||||
static fromObject(obj) {
|
||||
return new ForwardMapAccess(Object.keys(obj), Object.values(obj));
|
||||
}
|
||||
nextKeySeed(_seed) {
|
||||
return this.nextKey();
|
||||
}
|
||||
nextValueSeed(_seed) {
|
||||
return this.nextValue();
|
||||
}
|
||||
nextKey() {
|
||||
if (this.kindex < this.keys.length) {
|
||||
return utils_1.IterResult.Next(this.keys[this.kindex++]);
|
||||
}
|
||||
else {
|
||||
return utils_1.IterResult.Done();
|
||||
}
|
||||
}
|
||||
nextValue() {
|
||||
if (this.vindex < this.values.length) {
|
||||
return utils_1.IterResult.Next(this.values[this.vindex++]);
|
||||
}
|
||||
else {
|
||||
return utils_1.IterResult.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ForwardMapAccess = ForwardMapAccess;
|
||||
class ForwardIterableAccess extends interface_1.IterableAccess {
|
||||
constructor(items) {
|
||||
super();
|
||||
Object.defineProperty(this, "items", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "index", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
this.items = items;
|
||||
}
|
||||
nextElement() {
|
||||
if (this.index < this.items.length) {
|
||||
return utils_1.IterResult.Next(this.items[this.index++]);
|
||||
}
|
||||
else {
|
||||
return utils_1.IterResult.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ForwardIterableAccess = ForwardIterableAccess;
|
||||
class Forward {
|
||||
constructor(value) {
|
||||
Object.defineProperty(this, "value", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
this.value = value;
|
||||
}
|
||||
static with(value) {
|
||||
return new this(value);
|
||||
}
|
||||
deserializeAny(_visitor) {
|
||||
throw new Error("Can't forward to deserializeAny");
|
||||
}
|
||||
deserializeBoolean(visitor) {
|
||||
return visitor.visitBoolean(this.value);
|
||||
}
|
||||
deserializeNumber(visitor) {
|
||||
return visitor.visitNumber(this.value);
|
||||
}
|
||||
deserializeBigInt(visitor) {
|
||||
return visitor.visitBigInt(this.value);
|
||||
}
|
||||
deserializeString(visitor) {
|
||||
return visitor.visitString(this.value);
|
||||
}
|
||||
deserializeSymbol(visitor) {
|
||||
return visitor.visitSymbol(this.value);
|
||||
}
|
||||
deserializeNull(visitor) {
|
||||
return visitor.visitNull();
|
||||
}
|
||||
deserializeObject(visitor) {
|
||||
return visitor.visitObject(ForwardMapAccess.fromObject(this.value));
|
||||
}
|
||||
deserializeIterable(visitor) {
|
||||
return visitor.visitIterable(new ForwardIterableAccess(this.value));
|
||||
}
|
||||
deserializeFunction(_visitor) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
exports.Forward = Forward;
|
17
dist/de/generic.d.ts
vendored
Normal file
17
dist/de/generic.d.ts
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { IDeserializer, IIterableAccess, IMapAccess, IVisitor } from './interface';
|
||||
export declare class GenericSeed<T> {
|
||||
readonly visitor: IVisitor<T>;
|
||||
constructor(visitor?: IVisitor<T>);
|
||||
static deserialize<T, D extends IDeserializer>(deserializer: D, visitor?: IVisitor<T>): T;
|
||||
deserialize<D extends IDeserializer>(deserializer: D): T;
|
||||
}
|
||||
export declare class GenericVisitor<T> implements IVisitor<T> {
|
||||
visitBoolean(value: boolean): T;
|
||||
visitNumber(value: number): T;
|
||||
visitBigInt(value: bigint): T;
|
||||
visitString(value: string): T;
|
||||
visitSymbol(value: symbol): T;
|
||||
visitNull(): T;
|
||||
visitObject(access: IMapAccess): T;
|
||||
visitIterable(access: IIterableAccess): T;
|
||||
}
|
58
dist/de/generic.js
vendored
Normal file
58
dist/de/generic.js
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.GenericVisitor = exports.GenericSeed = void 0;
|
||||
class GenericSeed {
|
||||
constructor(visitor = new GenericVisitor()) {
|
||||
Object.defineProperty(this, "visitor", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
this.visitor = visitor;
|
||||
}
|
||||
static deserialize(deserializer, visitor = new GenericVisitor()) {
|
||||
return deserializer.deserializeAny(visitor);
|
||||
}
|
||||
deserialize(deserializer) {
|
||||
return GenericSeed.deserialize(deserializer, this.visitor);
|
||||
}
|
||||
}
|
||||
exports.GenericSeed = GenericSeed;
|
||||
class GenericVisitor {
|
||||
visitBoolean(value) {
|
||||
return value;
|
||||
}
|
||||
visitNumber(value) {
|
||||
return value;
|
||||
}
|
||||
visitBigInt(value) {
|
||||
return value;
|
||||
}
|
||||
visitString(value) {
|
||||
return value;
|
||||
}
|
||||
visitSymbol(value) {
|
||||
return value;
|
||||
}
|
||||
visitNull() {
|
||||
return null;
|
||||
}
|
||||
visitObject(access) {
|
||||
const result = [];
|
||||
let entry;
|
||||
while ((entry = access.nextEntry()) && !entry.done) {
|
||||
result.push(entry.value);
|
||||
}
|
||||
return Object.fromEntries(result);
|
||||
}
|
||||
visitIterable(access) {
|
||||
const result = [];
|
||||
let element;
|
||||
while ((element = access.nextElement())) {
|
||||
result.push(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.GenericVisitor = GenericVisitor;
|
105
dist/de/impl.d.ts
vendored
105
dist/de/impl.d.ts
vendored
|
@ -1,107 +1,4 @@
|
|||
import { Registry } from '../registry';
|
||||
import { Constructor } from '../utils';
|
||||
type Nullable<T> = T | undefined;
|
||||
export declare class IterResult {
|
||||
static Next<T>(value: T): IteratorResult<T>;
|
||||
static Done<T>(): IteratorResult<T>;
|
||||
}
|
||||
export interface IMapAccess {
|
||||
nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>;
|
||||
nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>;
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]>;
|
||||
nextKey<T>(): IteratorResult<T>;
|
||||
nextValue<V>(): IteratorResult<V>;
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]>;
|
||||
sizeHint?(): Nullable<number>;
|
||||
}
|
||||
export declare abstract class MapAccess {
|
||||
abstract nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>;
|
||||
abstract nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>;
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]>;
|
||||
abstract nextKey<T>(): IteratorResult<T>;
|
||||
abstract nextValue<V>(): IteratorResult<V>;
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]>;
|
||||
}
|
||||
export interface IIterableAccess {
|
||||
nextElement<T>(): IteratorResult<T>;
|
||||
sizeHint?(): Nullable<number>;
|
||||
}
|
||||
export declare abstract class IterableAccess implements IIterableAccess {
|
||||
abstract nextElement<T>(): IteratorResult<T>;
|
||||
}
|
||||
export interface IVisitor<T> {
|
||||
visitBoolean(value: boolean): T;
|
||||
visitNumber(value: number): T;
|
||||
visitBigInt(value: bigint): T;
|
||||
visitString(value: string): T;
|
||||
visitSymbol(value: symbol): T;
|
||||
visitNull(): T;
|
||||
visitObject(access: IMapAccess): T;
|
||||
visitIterable(access: IIterableAccess): T;
|
||||
}
|
||||
export declare class GenericSeed<T> {
|
||||
readonly visitor: IVisitor<T>;
|
||||
constructor(visitor?: IVisitor<T>);
|
||||
static deserialize<T, D extends IDeserializer>(deserializer: D, visitor?: IVisitor<T>): T;
|
||||
deserialize<D extends IDeserializer>(deserializer: D): T;
|
||||
}
|
||||
export declare class GenericVisitor<T> implements IVisitor<T> {
|
||||
visitBoolean(value: boolean): T;
|
||||
visitNumber(value: number): T;
|
||||
visitBigInt(value: bigint): T;
|
||||
visitString(value: string): T;
|
||||
visitSymbol(value: symbol): T;
|
||||
visitNull(): T;
|
||||
visitObject(access: IMapAccess): T;
|
||||
visitIterable(access: IIterableAccess): T;
|
||||
}
|
||||
export interface IDeserializer {
|
||||
deserializeAny<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeFunction<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
}
|
||||
export declare class ForwardMapAccess extends MapAccess {
|
||||
private readonly keys;
|
||||
private readonly values;
|
||||
private kindex;
|
||||
private vindex;
|
||||
constructor(keys: string[], values: any[]);
|
||||
static fromObject(obj: object): ForwardMapAccess;
|
||||
nextKeySeed<T, K extends Deserialize>(_seed: K): IteratorResult<T>;
|
||||
nextValueSeed<T, V extends Deserialize>(_seed: V): IteratorResult<T>;
|
||||
nextKey<T>(): IteratorResult<T>;
|
||||
nextValue<V>(): IteratorResult<V>;
|
||||
}
|
||||
export declare class ForwardIterableAccess extends IterableAccess {
|
||||
private readonly items;
|
||||
private index;
|
||||
constructor(items: any[]);
|
||||
nextElement<T>(): IteratorResult<T>;
|
||||
}
|
||||
export declare class Forward implements IDeserializer {
|
||||
private readonly value;
|
||||
constructor(value: any);
|
||||
static with(value: any): Forward;
|
||||
deserializeAny<T, V extends IVisitor<T>>(_visitor: V): T;
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeFunction<T, V extends IVisitor<T>>(_visitor: V): T;
|
||||
}
|
||||
export interface Deserialize {
|
||||
<T>(deserializer: IDeserializer): T;
|
||||
}
|
||||
import { IDeserializer } from './interface';
|
||||
export declare function deserialize<T, D extends IDeserializer>(deserializer: D, into: Constructor<T>, registry?: Registry): T;
|
||||
export {};
|
||||
|
|
220
dist/de/impl.js
vendored
220
dist/de/impl.js
vendored
|
@ -1,227 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Forward = exports.ForwardIterableAccess = exports.ForwardMapAccess = exports.GenericVisitor = exports.GenericSeed = exports.IterableAccess = exports.MapAccess = exports.IterResult = void 0;
|
||||
exports.deserialize = deserialize;
|
||||
const registry_1 = require("../registry");
|
||||
class IterResult {
|
||||
static Next(value) {
|
||||
return { done: false, value };
|
||||
}
|
||||
static Done() {
|
||||
return { done: true, value: undefined };
|
||||
}
|
||||
}
|
||||
exports.IterResult = IterResult;
|
||||
class MapAccess {
|
||||
nextEntrySeed(kseed, vseed) {
|
||||
const key = this.nextKeySeed(kseed);
|
||||
if (!key.done) {
|
||||
const value = this.nextValueSeed(vseed);
|
||||
if (!value.done) {
|
||||
return IterResult.Next([key.value, value.value]);
|
||||
}
|
||||
}
|
||||
return IterResult.Done();
|
||||
}
|
||||
nextEntry() {
|
||||
const key = this.nextKey();
|
||||
if (!key.done) {
|
||||
const value = this.nextValue();
|
||||
if (!value.done) {
|
||||
return IterResult.Next([key.value, value.value]);
|
||||
}
|
||||
}
|
||||
return IterResult.Done();
|
||||
}
|
||||
}
|
||||
exports.MapAccess = MapAccess;
|
||||
class IterableAccess {
|
||||
}
|
||||
exports.IterableAccess = IterableAccess;
|
||||
class GenericSeed {
|
||||
constructor(visitor = new GenericVisitor()) {
|
||||
Object.defineProperty(this, "visitor", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
this.visitor = visitor;
|
||||
}
|
||||
static deserialize(deserializer, visitor = new GenericVisitor()) {
|
||||
return deserializer.deserializeAny(visitor);
|
||||
}
|
||||
deserialize(deserializer) {
|
||||
return GenericSeed.deserialize(deserializer, this.visitor);
|
||||
}
|
||||
}
|
||||
exports.GenericSeed = GenericSeed;
|
||||
class GenericVisitor {
|
||||
visitBoolean(value) {
|
||||
return value;
|
||||
}
|
||||
visitNumber(value) {
|
||||
return value;
|
||||
}
|
||||
visitBigInt(value) {
|
||||
return value;
|
||||
}
|
||||
visitString(value) {
|
||||
return value;
|
||||
}
|
||||
visitSymbol(value) {
|
||||
return value;
|
||||
}
|
||||
visitNull() {
|
||||
return null;
|
||||
}
|
||||
visitObject(access) {
|
||||
const result = [];
|
||||
let entry;
|
||||
while ((entry = access.nextEntry()) && !entry.done) {
|
||||
result.push(entry.value);
|
||||
}
|
||||
return Object.fromEntries(result);
|
||||
}
|
||||
visitIterable(access) {
|
||||
const result = [];
|
||||
let element;
|
||||
while ((element = access.nextElement())) {
|
||||
result.push(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.GenericVisitor = GenericVisitor;
|
||||
class ForwardMapAccess extends MapAccess {
|
||||
constructor(keys, values) {
|
||||
super();
|
||||
Object.defineProperty(this, "keys", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "values", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "kindex", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
Object.defineProperty(this, "vindex", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
this.keys = keys;
|
||||
this.values = values;
|
||||
}
|
||||
static fromObject(obj) {
|
||||
return new ForwardMapAccess(Object.keys(obj), Object.values(obj));
|
||||
}
|
||||
nextKeySeed(_seed) {
|
||||
return this.nextKey();
|
||||
}
|
||||
nextValueSeed(_seed) {
|
||||
return this.nextValue();
|
||||
}
|
||||
nextKey() {
|
||||
if (this.kindex < this.keys.length) {
|
||||
return IterResult.Next(this.keys[this.kindex++]);
|
||||
}
|
||||
else {
|
||||
return IterResult.Done();
|
||||
}
|
||||
}
|
||||
nextValue() {
|
||||
if (this.vindex < this.values.length) {
|
||||
return IterResult.Next(this.values[this.vindex++]);
|
||||
}
|
||||
else {
|
||||
return IterResult.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ForwardMapAccess = ForwardMapAccess;
|
||||
class ForwardIterableAccess extends IterableAccess {
|
||||
constructor(items) {
|
||||
super();
|
||||
Object.defineProperty(this, "items", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "index", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
this.items = items;
|
||||
}
|
||||
nextElement() {
|
||||
if (this.index < this.items.length) {
|
||||
return IterResult.Next(this.items[this.index++]);
|
||||
}
|
||||
else {
|
||||
return IterResult.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ForwardIterableAccess = ForwardIterableAccess;
|
||||
class Forward {
|
||||
constructor(value) {
|
||||
Object.defineProperty(this, "value", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
this.value = value;
|
||||
}
|
||||
static with(value) {
|
||||
return new this(value);
|
||||
}
|
||||
deserializeAny(_visitor) {
|
||||
throw new Error("Can't forward to deserializeAny");
|
||||
}
|
||||
deserializeBoolean(visitor) {
|
||||
return visitor.visitBoolean(this.value);
|
||||
}
|
||||
deserializeNumber(visitor) {
|
||||
return visitor.visitNumber(this.value);
|
||||
}
|
||||
deserializeBigInt(visitor) {
|
||||
return visitor.visitBigInt(this.value);
|
||||
}
|
||||
deserializeString(visitor) {
|
||||
return visitor.visitString(this.value);
|
||||
}
|
||||
deserializeSymbol(visitor) {
|
||||
return visitor.visitSymbol(this.value);
|
||||
}
|
||||
deserializeNull(visitor) {
|
||||
return visitor.visitNull();
|
||||
}
|
||||
deserializeObject(visitor) {
|
||||
return visitor.visitObject(ForwardMapAccess.fromObject(this.value));
|
||||
}
|
||||
deserializeIterable(visitor) {
|
||||
return visitor.visitIterable(new ForwardIterableAccess(this.value));
|
||||
}
|
||||
deserializeFunction(_visitor) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
exports.Forward = Forward;
|
||||
function deserialize(deserializer, into, registry = registry_1.GlobalRegistry) {
|
||||
const de = registry.deserializers.get(into);
|
||||
if (de == null) {
|
||||
|
|
4
dist/de/index.d.ts
vendored
Normal file
4
dist/de/index.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
export * from './forward';
|
||||
export * from './generic';
|
||||
export * from './impl';
|
||||
export * from './interface';
|
20
dist/de/index.js
vendored
Normal file
20
dist/de/index.js
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./forward"), exports);
|
||||
__exportStar(require("./generic"), exports);
|
||||
__exportStar(require("./impl"), exports);
|
||||
__exportStar(require("./interface"), exports);
|
50
dist/de/interface.d.ts
vendored
Normal file
50
dist/de/interface.d.ts
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { Nullable } from "../utils";
|
||||
export interface IMapAccess {
|
||||
nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>;
|
||||
nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>;
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]>;
|
||||
nextKey<T>(): IteratorResult<T>;
|
||||
nextValue<V>(): IteratorResult<V>;
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]>;
|
||||
sizeHint?(): Nullable<number>;
|
||||
}
|
||||
export declare abstract class MapAccess {
|
||||
abstract nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>;
|
||||
abstract nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>;
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]>;
|
||||
abstract nextKey<T>(): IteratorResult<T>;
|
||||
abstract nextValue<V>(): IteratorResult<V>;
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]>;
|
||||
}
|
||||
export interface IIterableAccess {
|
||||
nextElement<T>(): IteratorResult<T>;
|
||||
sizeHint?(): Nullable<number>;
|
||||
}
|
||||
export declare abstract class IterableAccess implements IIterableAccess {
|
||||
abstract nextElement<T>(): IteratorResult<T>;
|
||||
}
|
||||
export interface IVisitor<T> {
|
||||
visitBoolean(value: boolean): T;
|
||||
visitNumber(value: number): T;
|
||||
visitBigInt(value: bigint): T;
|
||||
visitString(value: string): T;
|
||||
visitSymbol(value: symbol): T;
|
||||
visitNull(): T;
|
||||
visitObject(access: IMapAccess): T;
|
||||
visitIterable(access: IIterableAccess): T;
|
||||
}
|
||||
export interface IDeserializer {
|
||||
deserializeAny<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
deserializeFunction<T, V extends IVisitor<T>>(visitor: V): T;
|
||||
}
|
||||
export interface Deserialize {
|
||||
<T>(deserializer: IDeserializer): T;
|
||||
}
|
30
dist/de/interface.js
vendored
Normal file
30
dist/de/interface.js
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.IterableAccess = exports.MapAccess = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
class MapAccess {
|
||||
nextEntrySeed(kseed, vseed) {
|
||||
const key = this.nextKeySeed(kseed);
|
||||
if (!key.done) {
|
||||
const value = this.nextValueSeed(vseed);
|
||||
if (!value.done) {
|
||||
return utils_1.IterResult.Next([key.value, value.value]);
|
||||
}
|
||||
}
|
||||
return utils_1.IterResult.Done();
|
||||
}
|
||||
nextEntry() {
|
||||
const key = this.nextKey();
|
||||
if (!key.done) {
|
||||
const value = this.nextValue();
|
||||
if (!value.done) {
|
||||
return utils_1.IterResult.Next([key.value, value.value]);
|
||||
}
|
||||
}
|
||||
return utils_1.IterResult.Done();
|
||||
}
|
||||
}
|
||||
exports.MapAccess = MapAccess;
|
||||
class IterableAccess {
|
||||
}
|
||||
exports.IterableAccess = IterableAccess;
|
1
dist/index.d.ts
vendored
1
dist/index.d.ts
vendored
|
@ -1,3 +1,4 @@
|
|||
import '@tsmetadata/polyfill';
|
||||
export * as ser from './ser/impl';
|
||||
export * as de from './de/impl';
|
||||
export * from './case';
|
||||
|
|
1
dist/index.js
vendored
1
dist/index.js
vendored
|
@ -37,6 +37,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.de = exports.ser = void 0;
|
||||
require("@tsmetadata/polyfill");
|
||||
exports.ser = __importStar(require("./ser/impl"));
|
||||
exports.de = __importStar(require("./de/impl"));
|
||||
__exportStar(require("./case"), exports);
|
||||
|
|
4
dist/registry.d.ts
vendored
4
dist/registry.d.ts
vendored
|
@ -1,5 +1,5 @@
|
|||
import { Deserialize } from './de/impl';
|
||||
import { Serialize } from './ser/impl';
|
||||
import { Deserialize } from './de';
|
||||
import { Serialize } from './ser';
|
||||
export declare class Registry {
|
||||
serializers: Map<Function, Serialize<any>>;
|
||||
deserializers: Map<Function, Deserialize>;
|
||||
|
|
59
dist/ser/decorator.d.ts
vendored
Normal file
59
dist/ser/decorator.d.ts
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { CaseConvention } from '../case';
|
||||
import { Deserialize } from '../de';
|
||||
import { Nullable } from '../utils';
|
||||
import { Serialize } from './interface';
|
||||
export interface RenameOptions {
|
||||
serialize?: string;
|
||||
deserialize?: string;
|
||||
}
|
||||
export interface RenameAllOptions {
|
||||
serialize?: CaseConvention;
|
||||
deserialize?: CaseConvention;
|
||||
}
|
||||
export interface ContainerOptions {
|
||||
rename?: RenameOptions | string;
|
||||
renameAll?: RenameAllOptions | CaseConvention;
|
||||
default?: () => any;
|
||||
denyUnknownFields?: boolean;
|
||||
tag?: string;
|
||||
untagged?: boolean;
|
||||
}
|
||||
interface Predicate {
|
||||
<T>(value: T): boolean;
|
||||
}
|
||||
export interface SkipOptions {
|
||||
serialize?: Predicate | boolean;
|
||||
deserialize?: Predicate | boolean;
|
||||
}
|
||||
export interface PropertyOptions {
|
||||
alias?: string | string[];
|
||||
default?: () => any;
|
||||
flatten?: boolean;
|
||||
rename?: RenameOptions | string;
|
||||
skip?: SkipOptions | Predicate | boolean;
|
||||
serializeWith?: Serialize<any>;
|
||||
deserializeWith?: Deserialize;
|
||||
}
|
||||
export declare const Stage: Readonly<{
|
||||
readonly Serialize: 0;
|
||||
readonly Deserialize: 1;
|
||||
}>;
|
||||
export type Stage = typeof Stage[keyof typeof Stage];
|
||||
export declare class SerdeOptions {
|
||||
readonly target: Nullable<any>;
|
||||
readonly container: ContainerOptions;
|
||||
readonly properties: Map<string, PropertyOptions>;
|
||||
constructor(target: any, container?: ContainerOptions, properties?: Map<string, PropertyOptions>);
|
||||
private getClassName;
|
||||
getSerializedClassName(defaultName?: string): string | undefined;
|
||||
getDeserializedClassName(defaultName?: string): string | undefined;
|
||||
private applyPropertyCase;
|
||||
private getPropertyName;
|
||||
getSerializationPropertyName(property: string): string;
|
||||
getDeserializationPropertyName(property: string): string;
|
||||
private shouldSkip;
|
||||
shouldSerialize(property: string, value: any): boolean;
|
||||
shouldDeserialize(property: string, value: any): boolean;
|
||||
defaultFor(property: string): any;
|
||||
}
|
||||
export {};
|
146
dist/ser/decorator.js
vendored
Normal file
146
dist/ser/decorator.js
vendored
Normal file
|
@ -0,0 +1,146 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SerdeOptions = exports.Stage = void 0;
|
||||
const case_1 = require("../case");
|
||||
const utils_1 = require("../utils");
|
||||
exports.Stage = Object.freeze({
|
||||
Serialize: 0,
|
||||
Deserialize: 1
|
||||
});
|
||||
class SerdeOptions {
|
||||
constructor(target, container = {}, properties = new Map()) {
|
||||
Object.defineProperty(this, "target", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "container", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
Object.defineProperty(this, "properties", {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: void 0
|
||||
});
|
||||
this.target = target;
|
||||
this.container = container;
|
||||
this.properties = properties;
|
||||
}
|
||||
getClassName(stage, defaultName) {
|
||||
var _a, _b, _c, _d;
|
||||
if (defaultName === void 0) { defaultName = (_b = (_a = this.target) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name; }
|
||||
if ((0, utils_1.isString)(this.container.rename)) {
|
||||
return this.container.rename;
|
||||
}
|
||||
else if (stage === exports.Stage.Serialize && (0, utils_1.isString)((_c = this.container.rename) === null || _c === void 0 ? void 0 : _c.serialize)) {
|
||||
return this.container.rename.serialize;
|
||||
}
|
||||
else if (stage === exports.Stage.Deserialize && (0, utils_1.isString)((_d = this.container.rename) === null || _d === void 0 ? void 0 : _d.deserialize)) {
|
||||
return this.container.rename.serialize;
|
||||
}
|
||||
else {
|
||||
return defaultName;
|
||||
}
|
||||
}
|
||||
getSerializedClassName(defaultName) {
|
||||
var _a, _b;
|
||||
if (defaultName === void 0) { defaultName = (_b = (_a = this.target) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name; }
|
||||
return this.getClassName(exports.Stage.Serialize, defaultName);
|
||||
}
|
||||
getDeserializedClassName(defaultName) {
|
||||
var _a, _b;
|
||||
if (defaultName === void 0) { defaultName = (_b = (_a = this.target) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name; }
|
||||
return this.getClassName(exports.Stage.Deserialize, defaultName);
|
||||
}
|
||||
applyPropertyCase(stage, property) {
|
||||
var _a, _b;
|
||||
if ((0, utils_1.isNumber)(this.container.renameAll)) {
|
||||
return (0, case_1.convertCase)(property, this.container.renameAll);
|
||||
}
|
||||
else if (stage === exports.Stage.Serialize && (0, utils_1.isNumber)((_a = this.container.renameAll) === null || _a === void 0 ? void 0 : _a.serialize)) {
|
||||
return (0, case_1.convertCase)(property, this.container.renameAll.serialize);
|
||||
}
|
||||
else if (stage === exports.Stage.Deserialize && (0, utils_1.isNumber)((_b = this.container.renameAll) === null || _b === void 0 ? void 0 : _b.deserialize)) {
|
||||
return (0, case_1.convertCase)(property, this.container.renameAll.deserialize);
|
||||
}
|
||||
else {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
getPropertyName(stage, property) {
|
||||
var _a, _b;
|
||||
const options = this.properties.get(property);
|
||||
if (options == null) {
|
||||
return property;
|
||||
}
|
||||
else if ((0, utils_1.isString)(options.rename)) {
|
||||
return options.rename;
|
||||
}
|
||||
else if (stage == exports.Stage.Serialize && (0, utils_1.isString)((_a = options.rename) === null || _a === void 0 ? void 0 : _a.serialize)) {
|
||||
return options.rename.serialize;
|
||||
}
|
||||
else if (stage == exports.Stage.Deserialize && (0, utils_1.isString)((_b = options.rename) === null || _b === void 0 ? void 0 : _b.deserialize)) {
|
||||
return options.rename.deserialize;
|
||||
}
|
||||
else {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
getSerializationPropertyName(property) {
|
||||
const name = this.getPropertyName(exports.Stage.Serialize, property);
|
||||
return this.applyPropertyCase(exports.Stage.Serialize, name);
|
||||
}
|
||||
getDeserializationPropertyName(property) {
|
||||
const name = this.getPropertyName(exports.Stage.Deserialize, property);
|
||||
return this.applyPropertyCase(exports.Stage.Deserialize, name);
|
||||
}
|
||||
shouldSkip(stage, property, value) {
|
||||
var _a, _b, _c, _d;
|
||||
const options = this.properties.get(property);
|
||||
if (options == null) {
|
||||
return false;
|
||||
}
|
||||
else if (typeof options.skip === 'boolean') {
|
||||
return options.skip;
|
||||
}
|
||||
else if ((0, utils_1.isFunction)(options.skip)) {
|
||||
return options.skip(value);
|
||||
}
|
||||
else if (stage === exports.Stage.Serialize && typeof ((_a = options.skip) === null || _a === void 0 ? void 0 : _a.serialize) === 'boolean') {
|
||||
return options.skip.serialize;
|
||||
}
|
||||
else if (stage === exports.Stage.Serialize && (0, utils_1.isFunction)((_b = options.skip) === null || _b === void 0 ? void 0 : _b.serialize)) {
|
||||
return options.skip.serialize(value);
|
||||
}
|
||||
else if (stage === exports.Stage.Deserialize && typeof ((_c = options.skip) === null || _c === void 0 ? void 0 : _c.deserialize) === 'boolean') {
|
||||
return options.skip.deserialize;
|
||||
}
|
||||
else if (stage === exports.Stage.Deserialize && (0, utils_1.isFunction)((_d = options.skip) === null || _d === void 0 ? void 0 : _d.deserialize)) {
|
||||
return options.skip.deserialize(value);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
shouldSerialize(property, value) {
|
||||
return !this.shouldSkip(exports.Stage.Serialize, property, value);
|
||||
}
|
||||
shouldDeserialize(property, value) {
|
||||
return !this.shouldSkip(exports.Stage.Deserialize, property, value);
|
||||
}
|
||||
defaultFor(property) {
|
||||
const options = this.properties.get(property);
|
||||
if (options != null && (0, utils_1.isFunction)(options.default)) {
|
||||
return options.default();
|
||||
}
|
||||
else if ((0, utils_1.isFunction)(this.container.default)) {
|
||||
return this.container.default();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.SerdeOptions = SerdeOptions;
|
50
dist/ser/impl.d.ts
vendored
50
dist/ser/impl.d.ts
vendored
|
@ -1,46 +1,4 @@
|
|||
export interface ISerializeObject<T> {
|
||||
serializeKey(key: string): void;
|
||||
serializeValue<U>(value: U): void;
|
||||
serializeEntry<U>(key: string, value: U): void;
|
||||
end(): T;
|
||||
}
|
||||
export declare abstract class SerializeObject<T> implements ISerializeObject<T> {
|
||||
abstract serializeKey(key: string): void;
|
||||
abstract serializeValue<U>(value: U): void;
|
||||
abstract end(): T;
|
||||
serializeEntry<U>(key: string, value: U): void;
|
||||
}
|
||||
export interface ISerializeIterable<T> {
|
||||
serializeElement<U>(value: U): void;
|
||||
end(): T;
|
||||
}
|
||||
export declare abstract class SerializeIterable<T> implements ISerializeIterable<T> {
|
||||
abstract serializeElement<U>(value: U): void;
|
||||
abstract end(): T;
|
||||
}
|
||||
export interface ISerializer<T> {
|
||||
serializeAny(value: any): T;
|
||||
serializeBoolean(value: boolean): T;
|
||||
serializeNumber(value: number): T;
|
||||
serializeBigInt(value: bigint): T;
|
||||
serializeString(value: string): T;
|
||||
serializeSymbol(value: symbol): T;
|
||||
serializeNull(): T;
|
||||
serializeObject(): ISerializeObject<T>;
|
||||
serializeClass(name: string): ISerializeObject<T>;
|
||||
}
|
||||
export declare class Serializer<T> implements ISerializer<T> {
|
||||
serializeAny(_value: any): T;
|
||||
serializeBoolean(_value: boolean): T;
|
||||
serializeNumber(_value: number): T;
|
||||
serializeBigInt(_value: bigint): T;
|
||||
serializeString(_value: string): T;
|
||||
serializeSymbol(_value: symbol): T;
|
||||
serializeNull(): T;
|
||||
serializeObject(): ISerializeObject<T>;
|
||||
serializeClass(_name: string): ISerializeObject<T>;
|
||||
}
|
||||
export interface Serialize<T> {
|
||||
<U, S extends Serializer<U>>(serializer: S, value: T): U;
|
||||
}
|
||||
export declare function serialize<T, V, S extends Serializer<T>>(serializer: S, value: V): T;
|
||||
import { SerdeOptions } from './decorator';
|
||||
import { Serializer } from './interface';
|
||||
import { Nullable } from '../utils';
|
||||
export declare function serialize<T, V, S extends Serializer<T>>(serializer: S, value: V, optionsGetter?: (value: V) => Nullable<SerdeOptions>): T;
|
||||
|
|
76
dist/ser/impl.js
vendored
76
dist/ser/impl.js
vendored
|
@ -1,77 +1,41 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Serializer = exports.SerializeIterable = exports.SerializeObject = void 0;
|
||||
exports.serialize = serialize;
|
||||
class SerializeObject {
|
||||
serializeEntry(key, value) {
|
||||
this.serializeKey(key);
|
||||
this.serializeValue(value);
|
||||
}
|
||||
}
|
||||
exports.SerializeObject = SerializeObject;
|
||||
class SerializeIterable {
|
||||
}
|
||||
exports.SerializeIterable = SerializeIterable;
|
||||
class Serializer {
|
||||
serializeAny(_value) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
serializeBoolean(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeNumber(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeBigInt(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeString(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeSymbol(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeNull() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeObject() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeClass(_name) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
exports.Serializer = Serializer;
|
||||
const isPlainObject = (value) => (value === null || value === void 0 ? void 0 : value.constructor) === Object;
|
||||
const utils_1 = require("../utils");
|
||||
class UnhandledTypeError extends TypeError {
|
||||
constructor(serializer, value) {
|
||||
super(`unhandled type: "${typeof value}" for serializer ${serializer.constructor.name}`);
|
||||
super(`unhandled type: '${typeof value}' for serializer ${serializer.constructor.name}`);
|
||||
}
|
||||
}
|
||||
function serializeObject(serializer, obj) {
|
||||
function serializeObject(serializer, obj, options) {
|
||||
for (const key in obj) {
|
||||
serializer.serializeEntry(key, obj[key]);
|
||||
}
|
||||
return serializer.end();
|
||||
}
|
||||
function serializeClass(serializer, value) {
|
||||
function serializeClass(serializer, value, options) {
|
||||
const name = value.constructor.name;
|
||||
const ser = serializer.serializeClass(name);
|
||||
return serializeObject(ser, value);
|
||||
return serializeObject(ser, value, options);
|
||||
}
|
||||
function serialize(serializer, value) {
|
||||
const defaultGetter = (value) => {
|
||||
var _a;
|
||||
return (_a = value[Symbol.metadata]) === null || _a === void 0 ? void 0 : _a.serde;
|
||||
};
|
||||
function serialize(serializer, value, optionsGetter = defaultGetter) {
|
||||
switch (typeof value) {
|
||||
case "string": return serializer.serializeString(value);
|
||||
case "number": return serializer.serializeNumber(value);
|
||||
case "bigint": return serializer.serializeBigInt(value);
|
||||
case "boolean": return serializer.serializeBoolean(value);
|
||||
case "symbol": return serializer.serializeSymbol(value);
|
||||
case "undefined": return serializer.serializeNull();
|
||||
case "object":
|
||||
case 'string': return serializer.serializeString(value);
|
||||
case 'number': return serializer.serializeNumber(value);
|
||||
case 'bigint': return serializer.serializeBigInt(value);
|
||||
case 'boolean': return serializer.serializeBoolean(value);
|
||||
case 'symbol': return serializer.serializeSymbol(value);
|
||||
case 'undefined': return serializer.serializeNull();
|
||||
case 'object':
|
||||
const options = optionsGetter(value);
|
||||
switch (true) {
|
||||
case value == null: return serializer.serializeNull();
|
||||
case !isPlainObject(value): return serializeClass(serializer, value);
|
||||
default: return serializeObject(serializer.serializeObject(), value);
|
||||
case !(0, utils_1.isPlainObject)(value): return serializeClass(serializer, value, options);
|
||||
default: return serializeObject(serializer.serializeObject(), value, options);
|
||||
}
|
||||
default: throw new UnhandledTypeError(serializer, value);
|
||||
}
|
||||
|
|
2
dist/ser/index.d.ts
vendored
Normal file
2
dist/ser/index.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from './impl';
|
||||
export * from './interface';
|
18
dist/ser/index.js
vendored
Normal file
18
dist/ser/index.js
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./impl"), exports);
|
||||
__exportStar(require("./interface"), exports);
|
45
dist/ser/interface.d.ts
vendored
Normal file
45
dist/ser/interface.d.ts
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
export interface ISerializeObject<T> {
|
||||
serializeKey(key: string): void;
|
||||
serializeValue<U>(value: U): void;
|
||||
serializeEntry<U>(key: string, value: U): void;
|
||||
end(): T;
|
||||
}
|
||||
export declare abstract class SerializeObject<T> implements ISerializeObject<T> {
|
||||
abstract serializeKey(key: string): void;
|
||||
abstract serializeValue<U>(value: U): void;
|
||||
abstract end(): T;
|
||||
serializeEntry<U>(key: string, value: U): void;
|
||||
}
|
||||
export interface ISerializeIterable<T> {
|
||||
serializeElement<U>(value: U): void;
|
||||
end(): T;
|
||||
}
|
||||
export declare abstract class SerializeIterable<T> implements ISerializeIterable<T> {
|
||||
abstract serializeElement<U>(value: U): void;
|
||||
abstract end(): T;
|
||||
}
|
||||
export interface ISerializer<T> {
|
||||
serializeAny(value: any): T;
|
||||
serializeBoolean(value: boolean): T;
|
||||
serializeNumber(value: number): T;
|
||||
serializeBigInt(value: bigint): T;
|
||||
serializeString(value: string): T;
|
||||
serializeSymbol(value: symbol): T;
|
||||
serializeNull(): T;
|
||||
serializeObject(): ISerializeObject<T>;
|
||||
serializeClass(name: string): ISerializeObject<T>;
|
||||
}
|
||||
export declare class Serializer<T> implements ISerializer<T> {
|
||||
serializeAny(_value: any): T;
|
||||
serializeBoolean(_value: boolean): T;
|
||||
serializeNumber(_value: number): T;
|
||||
serializeBigInt(_value: bigint): T;
|
||||
serializeString(_value: string): T;
|
||||
serializeSymbol(_value: symbol): T;
|
||||
serializeNull(): T;
|
||||
serializeObject(): ISerializeObject<T>;
|
||||
serializeClass(_name: string): ISerializeObject<T>;
|
||||
}
|
||||
export interface Serialize<T> {
|
||||
<U, S extends Serializer<U>>(serializer: S, value: T): U;
|
||||
}
|
43
dist/ser/interface.js
vendored
Normal file
43
dist/ser/interface.js
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Serializer = exports.SerializeIterable = exports.SerializeObject = void 0;
|
||||
class SerializeObject {
|
||||
serializeEntry(key, value) {
|
||||
this.serializeKey(key);
|
||||
this.serializeValue(value);
|
||||
}
|
||||
}
|
||||
exports.SerializeObject = SerializeObject;
|
||||
class SerializeIterable {
|
||||
}
|
||||
exports.SerializeIterable = SerializeIterable;
|
||||
class Serializer {
|
||||
serializeAny(_value) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
serializeBoolean(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeNumber(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeBigInt(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeString(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeSymbol(_value) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeNull() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeObject() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
serializeClass(_name) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
exports.Serializer = Serializer;
|
4
dist/utils.d.ts
vendored
4
dist/utils.d.ts
vendored
|
@ -13,3 +13,7 @@ export declare function isIterable(value: any): value is Iterable<any>;
|
|||
export declare function isString(value: any): value is string;
|
||||
export declare function isNumber(value: any): value is number;
|
||||
export type Constructor<T = any> = new (...args: any[]) => T;
|
||||
export declare class IterResult {
|
||||
static Next<T>(value: T): IteratorResult<T>;
|
||||
static Done<T>(): IteratorResult<T>;
|
||||
}
|
||||
|
|
10
dist/utils.js
vendored
10
dist/utils.js
vendored
|
@ -1,5 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.IterResult = void 0;
|
||||
exports.staticImplements = staticImplements;
|
||||
exports.isPlainObject = isPlainObject;
|
||||
exports.isFunction = isFunction;
|
||||
|
@ -24,3 +25,12 @@ function isString(value) {
|
|||
function isNumber(value) {
|
||||
return !isNaN(value);
|
||||
}
|
||||
class IterResult {
|
||||
static Next(value) {
|
||||
return { done: false, value };
|
||||
}
|
||||
static Done() {
|
||||
return { done: true, value: undefined };
|
||||
}
|
||||
}
|
||||
exports.IterResult = IterResult;
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
"default": "./dist/index.js"
|
||||
},
|
||||
"./ser": {
|
||||
"types": "./dist/ser/impl.d.ts",
|
||||
"default": "./dist/ser/impl.js"
|
||||
"types": "./dist/ser/index.d.ts",
|
||||
"default": "./dist/ser/index.js"
|
||||
},
|
||||
"./de": {
|
||||
"types": "./dist/de/impl.d.ts",
|
||||
"default": "./dist/de/impl.js"
|
||||
"types": "./dist/de/index.d.ts",
|
||||
"default": "./dist/de/index.js"
|
||||
},
|
||||
"./utils": {
|
||||
"types": "./dist/utils.d.ts",
|
||||
|
|
118
src/de/forward.ts
Normal file
118
src/de/forward.ts
Normal file
|
@ -0,0 +1,118 @@
|
|||
import { IterResult } from '../utils'
|
||||
import { Deserialize, IDeserializer, IterableAccess, IVisitor, MapAccess } from './interface'
|
||||
|
||||
export class ForwardMapAccess extends MapAccess {
|
||||
private readonly keys: string[]
|
||||
private readonly values: any[]
|
||||
|
||||
private kindex: number = 0
|
||||
private vindex: number = 0
|
||||
|
||||
constructor(keys: string[], values: any[]) {
|
||||
super()
|
||||
this.keys = keys
|
||||
this.values = values
|
||||
}
|
||||
|
||||
static fromObject(obj: object): ForwardMapAccess {
|
||||
return new ForwardMapAccess(
|
||||
Object.keys(obj),
|
||||
Object.values(obj)
|
||||
)
|
||||
}
|
||||
|
||||
nextKeySeed<T, K extends Deserialize>(_seed: K): IteratorResult<T> {
|
||||
return this.nextKey()
|
||||
}
|
||||
|
||||
nextValueSeed<T, V extends Deserialize>(_seed: V): IteratorResult<T> {
|
||||
return this.nextValue()
|
||||
}
|
||||
|
||||
nextKey<T>(): IteratorResult<T> {
|
||||
if (this.kindex < this.keys.length) {
|
||||
return IterResult.Next(this.keys[this.kindex++]) as IteratorResult<T>
|
||||
} else {
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
|
||||
nextValue<V>(): IteratorResult<V> {
|
||||
if (this.vindex < this.values.length) {
|
||||
return IterResult.Next(this.values[this.vindex++]) as IteratorResult<V>
|
||||
} else {
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ForwardIterableAccess extends IterableAccess {
|
||||
private readonly items: any[]
|
||||
private index: number = 0
|
||||
|
||||
constructor(items: any[]) {
|
||||
super()
|
||||
this.items = items
|
||||
}
|
||||
|
||||
nextElement<T>(): IteratorResult<T> {
|
||||
if (this.index < this.items.length) {
|
||||
return IterResult.Next(this.items[this.index++]) as IteratorResult<T>
|
||||
} else {
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Forward implements IDeserializer {
|
||||
private readonly value: any
|
||||
|
||||
constructor(value: any) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
static with(value: any): Forward {
|
||||
return new this(value)
|
||||
}
|
||||
|
||||
deserializeAny<T, V extends IVisitor<T>>(_visitor: V): T {
|
||||
throw new Error("Can't forward to deserializeAny")
|
||||
}
|
||||
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitBoolean(this.value)
|
||||
}
|
||||
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitNumber(this.value)
|
||||
}
|
||||
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitBigInt(this.value)
|
||||
}
|
||||
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitString(this.value)
|
||||
}
|
||||
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitSymbol(this.value)
|
||||
}
|
||||
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitNull()
|
||||
}
|
||||
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitObject(ForwardMapAccess.fromObject(this.value))
|
||||
}
|
||||
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitIterable(new ForwardIterableAccess(this.value))
|
||||
}
|
||||
|
||||
deserializeFunction<T, V extends IVisitor<T>>(_visitor: V): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
}
|
||||
|
68
src/de/generic.ts
Normal file
68
src/de/generic.ts
Normal file
|
@ -0,0 +1,68 @@
|
|||
import { IDeserializer, IIterableAccess, IMapAccess, IVisitor } from './interface'
|
||||
|
||||
export class GenericSeed<T> {
|
||||
readonly visitor: IVisitor<T>
|
||||
|
||||
constructor(visitor: IVisitor<T> = new GenericVisitor()) {
|
||||
this.visitor = visitor
|
||||
}
|
||||
|
||||
static deserialize<T, D extends IDeserializer>(deserializer: D, visitor: IVisitor<T> = new GenericVisitor()): T {
|
||||
return deserializer.deserializeAny(visitor)
|
||||
}
|
||||
|
||||
deserialize<D extends IDeserializer>(deserializer: D): T {
|
||||
return GenericSeed.deserialize(deserializer, this.visitor)
|
||||
}
|
||||
}
|
||||
|
||||
export class GenericVisitor<T> implements IVisitor<T> {
|
||||
visitBoolean(value: boolean): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitNumber(value: number): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitBigInt(value: bigint): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitString(value: string): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitSymbol(value: symbol): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitNull(): T {
|
||||
return null as T
|
||||
}
|
||||
|
||||
visitObject(access: IMapAccess): T {
|
||||
const result = []
|
||||
let entry
|
||||
|
||||
while ((entry = access.nextEntry()) && !entry.done) {
|
||||
result.push(entry.value)
|
||||
}
|
||||
|
||||
return Object.fromEntries(result)
|
||||
}
|
||||
|
||||
visitIterable(access: IIterableAccess): T {
|
||||
const result = []
|
||||
let element
|
||||
|
||||
while ((element = access.nextElement())) {
|
||||
result.push(element)
|
||||
}
|
||||
|
||||
return result as T
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
275
src/de/impl.ts
275
src/de/impl.ts
|
@ -1,279 +1,6 @@
|
|||
import { GlobalRegistry, Registry } from '../registry'
|
||||
import { Constructor } from '../utils'
|
||||
|
||||
type Nullable<T> = T | undefined
|
||||
|
||||
export class IterResult {
|
||||
static Next<T>(value: T): IteratorResult<T> {
|
||||
return { done: false, value }
|
||||
}
|
||||
|
||||
static Done<T>(): IteratorResult<T> {
|
||||
return { done: true, value: undefined }
|
||||
}
|
||||
}
|
||||
|
||||
export interface IMapAccess {
|
||||
nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>
|
||||
nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]>
|
||||
nextKey<T>(): IteratorResult<T>
|
||||
nextValue<V>(): IteratorResult<V>
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]>
|
||||
sizeHint?(): Nullable<number>
|
||||
}
|
||||
|
||||
export abstract class MapAccess {
|
||||
abstract nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>
|
||||
abstract nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>
|
||||
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]> {
|
||||
const key = this.nextKeySeed(kseed) as IteratorResult<TK>
|
||||
|
||||
if (!key.done) {
|
||||
const value = this.nextValueSeed(vseed) as IteratorResult<TV>
|
||||
|
||||
if (!value.done) {
|
||||
return IterResult.Next([key.value, value.value])
|
||||
}
|
||||
}
|
||||
|
||||
return IterResult.Done()
|
||||
}
|
||||
|
||||
abstract nextKey<T>(): IteratorResult<T>
|
||||
abstract nextValue<V>(): IteratorResult<V>
|
||||
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]> {
|
||||
const key = this.nextKey() as IteratorResult<K>
|
||||
|
||||
if (!key.done) {
|
||||
const value = this.nextValue() as IteratorResult<V>
|
||||
|
||||
if (!value.done) {
|
||||
return IterResult.Next([key.value, value.value])
|
||||
}
|
||||
}
|
||||
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
|
||||
export interface IIterableAccess {
|
||||
nextElement<T>(): IteratorResult<T>
|
||||
sizeHint?(): Nullable<number>
|
||||
}
|
||||
|
||||
export abstract class IterableAccess implements IIterableAccess {
|
||||
abstract nextElement<T>(): IteratorResult<T>
|
||||
}
|
||||
|
||||
export interface IVisitor<T> {
|
||||
visitBoolean(value: boolean): T
|
||||
visitNumber(value: number): T
|
||||
visitBigInt(value: bigint): T
|
||||
visitString(value: string): T
|
||||
visitSymbol(value: symbol): T
|
||||
visitNull(): T
|
||||
visitObject(access: IMapAccess): T
|
||||
visitIterable(access: IIterableAccess): T
|
||||
}
|
||||
|
||||
export class GenericSeed<T> {
|
||||
readonly visitor: IVisitor<T>
|
||||
|
||||
constructor(visitor: IVisitor<T> = new GenericVisitor()) {
|
||||
this.visitor = visitor
|
||||
}
|
||||
|
||||
static deserialize<T, D extends IDeserializer>(deserializer: D, visitor: IVisitor<T> = new GenericVisitor()): T {
|
||||
return deserializer.deserializeAny(visitor)
|
||||
}
|
||||
|
||||
deserialize<D extends IDeserializer>(deserializer: D): T {
|
||||
return GenericSeed.deserialize(deserializer, this.visitor)
|
||||
}
|
||||
}
|
||||
|
||||
export class GenericVisitor<T> implements IVisitor<T> {
|
||||
visitBoolean(value: boolean): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitNumber(value: number): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitBigInt(value: bigint): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitString(value: string): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitSymbol(value: symbol): T {
|
||||
return value as T
|
||||
}
|
||||
|
||||
visitNull(): T {
|
||||
return null as T
|
||||
}
|
||||
|
||||
visitObject(access: IMapAccess): T {
|
||||
const result = []
|
||||
let entry
|
||||
|
||||
while ((entry = access.nextEntry()) && !entry.done) {
|
||||
result.push(entry.value)
|
||||
}
|
||||
|
||||
return Object.fromEntries(result)
|
||||
}
|
||||
|
||||
visitIterable(access: IIterableAccess): T {
|
||||
const result = []
|
||||
let element
|
||||
|
||||
while ((element = access.nextElement())) {
|
||||
result.push(element)
|
||||
}
|
||||
|
||||
return result as T
|
||||
}
|
||||
}
|
||||
|
||||
export interface IDeserializer {
|
||||
deserializeAny<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeFunction<T, V extends IVisitor<T>>(visitor: V): T
|
||||
}
|
||||
|
||||
export class ForwardMapAccess extends MapAccess {
|
||||
private readonly keys: string[]
|
||||
private readonly values: any[]
|
||||
|
||||
private kindex: number = 0
|
||||
private vindex: number = 0
|
||||
|
||||
constructor(keys: string[], values: any[]) {
|
||||
super()
|
||||
this.keys = keys
|
||||
this.values = values
|
||||
}
|
||||
|
||||
static fromObject(obj: object): ForwardMapAccess {
|
||||
return new ForwardMapAccess(
|
||||
Object.keys(obj),
|
||||
Object.values(obj)
|
||||
)
|
||||
}
|
||||
|
||||
nextKeySeed<T, K extends Deserialize>(_seed: K): IteratorResult<T> {
|
||||
return this.nextKey()
|
||||
}
|
||||
|
||||
nextValueSeed<T, V extends Deserialize>(_seed: V): IteratorResult<T> {
|
||||
return this.nextValue()
|
||||
}
|
||||
|
||||
nextKey<T>(): IteratorResult<T> {
|
||||
if (this.kindex < this.keys.length) {
|
||||
return IterResult.Next(this.keys[this.kindex++]) as IteratorResult<T>
|
||||
} else {
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
|
||||
nextValue<V>(): IteratorResult<V> {
|
||||
if (this.vindex < this.values.length) {
|
||||
return IterResult.Next(this.values[this.vindex++]) as IteratorResult<V>
|
||||
} else {
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ForwardIterableAccess extends IterableAccess {
|
||||
private readonly items: any[]
|
||||
private index: number = 0
|
||||
|
||||
constructor(items: any[]) {
|
||||
super()
|
||||
this.items = items
|
||||
}
|
||||
|
||||
nextElement<T>(): IteratorResult<T> {
|
||||
if (this.index < this.items.length) {
|
||||
return IterResult.Next(this.items[this.index++]) as IteratorResult<T>
|
||||
} else {
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Forward implements IDeserializer {
|
||||
private readonly value: any
|
||||
|
||||
constructor(value: any) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
static with(value: any): Forward {
|
||||
return new this(value)
|
||||
}
|
||||
|
||||
deserializeAny<T, V extends IVisitor<T>>(_visitor: V): T {
|
||||
throw new Error("Can't forward to deserializeAny")
|
||||
}
|
||||
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitBoolean(this.value)
|
||||
}
|
||||
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitNumber(this.value)
|
||||
}
|
||||
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitBigInt(this.value)
|
||||
}
|
||||
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitString(this.value)
|
||||
}
|
||||
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitSymbol(this.value)
|
||||
}
|
||||
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitNull()
|
||||
}
|
||||
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitObject(ForwardMapAccess.fromObject(this.value))
|
||||
}
|
||||
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T {
|
||||
return visitor.visitIterable(new ForwardIterableAccess(this.value))
|
||||
}
|
||||
|
||||
deserializeFunction<T, V extends IVisitor<T>>(_visitor: V): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
}
|
||||
|
||||
export interface Deserialize {
|
||||
<T>(deserializer: IDeserializer): T
|
||||
}
|
||||
import { IDeserializer } from './interface'
|
||||
|
||||
export function deserialize<T, D extends IDeserializer>(deserializer: D, into: Constructor<T>, registry: Registry = GlobalRegistry): T {
|
||||
const de = registry.deserializers.get(into)
|
||||
|
|
5
src/de/index.ts
Normal file
5
src/de/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export * from './forward'
|
||||
export * from './generic'
|
||||
export * from './impl'
|
||||
export * from './interface'
|
||||
|
85
src/de/interface.ts
Normal file
85
src/de/interface.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
import { IterResult, Nullable } from "../utils"
|
||||
|
||||
export interface IMapAccess {
|
||||
nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>
|
||||
nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]>
|
||||
nextKey<T>(): IteratorResult<T>
|
||||
nextValue<V>(): IteratorResult<V>
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]>
|
||||
sizeHint?(): Nullable<number>
|
||||
}
|
||||
|
||||
export abstract class MapAccess {
|
||||
abstract nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T>
|
||||
abstract nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T>
|
||||
|
||||
nextEntrySeed<TK, TV, K extends Deserialize, V extends Deserialize>(kseed: K, vseed: V): IteratorResult<[TK, TV]> {
|
||||
const key = this.nextKeySeed(kseed) as IteratorResult<TK>
|
||||
|
||||
if (!key.done) {
|
||||
const value = this.nextValueSeed(vseed) as IteratorResult<TV>
|
||||
|
||||
if (!value.done) {
|
||||
return IterResult.Next([key.value, value.value])
|
||||
}
|
||||
}
|
||||
|
||||
return IterResult.Done()
|
||||
}
|
||||
|
||||
abstract nextKey<T>(): IteratorResult<T>
|
||||
abstract nextValue<V>(): IteratorResult<V>
|
||||
|
||||
nextEntry<K, V>(): IteratorResult<[K, V]> {
|
||||
const key = this.nextKey() as IteratorResult<K>
|
||||
|
||||
if (!key.done) {
|
||||
const value = this.nextValue() as IteratorResult<V>
|
||||
|
||||
if (!value.done) {
|
||||
return IterResult.Next([key.value, value.value])
|
||||
}
|
||||
}
|
||||
|
||||
return IterResult.Done()
|
||||
}
|
||||
}
|
||||
|
||||
export interface IIterableAccess {
|
||||
nextElement<T>(): IteratorResult<T>
|
||||
sizeHint?(): Nullable<number>
|
||||
}
|
||||
|
||||
export abstract class IterableAccess implements IIterableAccess {
|
||||
abstract nextElement<T>(): IteratorResult<T>
|
||||
}
|
||||
|
||||
export interface IVisitor<T> {
|
||||
visitBoolean(value: boolean): T
|
||||
visitNumber(value: number): T
|
||||
visitBigInt(value: bigint): T
|
||||
visitString(value: string): T
|
||||
visitSymbol(value: symbol): T
|
||||
visitNull(): T
|
||||
visitObject(access: IMapAccess): T
|
||||
visitIterable(access: IIterableAccess): T
|
||||
}
|
||||
|
||||
export interface IDeserializer {
|
||||
deserializeAny<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeString<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeSymbol<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T
|
||||
deserializeFunction<T, V extends IVisitor<T>>(visitor: V): T
|
||||
}
|
||||
|
||||
export interface Deserialize {
|
||||
<T>(deserializer: IDeserializer): T
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
import '@tsmetadata/polyfill'
|
||||
|
||||
export * as ser from './ser/impl'
|
||||
export * as de from './de/impl'
|
||||
export * from './case'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Deserialize } from './de/impl'
|
||||
import { Serialize } from './ser/impl'
|
||||
import { Deserialize } from './de'
|
||||
import { Serialize } from './ser'
|
||||
|
||||
export class Registry {
|
||||
serializers: Map<Function, Serialize<any>> = new Map()
|
||||
|
|
157
src/ser/decorator.ts
Normal file
157
src/ser/decorator.ts
Normal file
|
@ -0,0 +1,157 @@
|
|||
import { CaseConvention, convertCase } from '../case'
|
||||
import { Deserialize } from '../de'
|
||||
import { isFunction, isNumber, isString, Nullable } from '../utils'
|
||||
import { Serialize } from './interface'
|
||||
|
||||
export interface RenameOptions {
|
||||
serialize?: string
|
||||
deserialize?: string
|
||||
}
|
||||
|
||||
export interface RenameAllOptions {
|
||||
serialize?: CaseConvention
|
||||
deserialize?: CaseConvention
|
||||
}
|
||||
|
||||
export interface ContainerOptions {
|
||||
rename?: RenameOptions | string
|
||||
renameAll?: RenameAllOptions | CaseConvention
|
||||
default?: () => any
|
||||
denyUnknownFields?: boolean
|
||||
tag?: string
|
||||
untagged?: boolean
|
||||
}
|
||||
|
||||
interface Predicate {
|
||||
<T>(value: T): boolean
|
||||
}
|
||||
|
||||
export interface SkipOptions {
|
||||
serialize?: Predicate | boolean
|
||||
deserialize?: Predicate | boolean
|
||||
}
|
||||
export interface PropertyOptions {
|
||||
alias?: string | string[]
|
||||
default?: () => any
|
||||
flatten?: boolean
|
||||
rename?: RenameOptions | string
|
||||
skip?: SkipOptions | Predicate | boolean
|
||||
serializeWith?: Serialize<any>
|
||||
deserializeWith?: Deserialize
|
||||
}
|
||||
|
||||
export const Stage = Object.freeze({
|
||||
Serialize: 0,
|
||||
Deserialize: 1
|
||||
} as const)
|
||||
|
||||
export type Stage = typeof Stage[keyof typeof Stage]
|
||||
|
||||
export class SerdeOptions {
|
||||
readonly target: Nullable<any>
|
||||
readonly container: ContainerOptions
|
||||
readonly properties: Map<string, PropertyOptions>
|
||||
|
||||
constructor(target: any, container: ContainerOptions = {}, properties: Map<string, PropertyOptions> = new Map()) {
|
||||
this.target = target
|
||||
this.container = container
|
||||
this.properties = properties
|
||||
}
|
||||
|
||||
private getClassName(stage: Stage, defaultName: string = this.target?.constructor?.name) {
|
||||
if (isString(this.container.rename)) {
|
||||
return this.container.rename
|
||||
} else if (stage === Stage.Serialize && isString(this.container.rename?.serialize)) {
|
||||
return this.container.rename.serialize
|
||||
} else if (stage === Stage.Deserialize && isString(this.container.rename?.deserialize)) {
|
||||
return this.container.rename.serialize
|
||||
} else {
|
||||
return defaultName
|
||||
}
|
||||
}
|
||||
|
||||
getSerializedClassName(defaultName: string = this.target?.constructor?.name) {
|
||||
return this.getClassName(Stage.Serialize, defaultName)
|
||||
}
|
||||
|
||||
getDeserializedClassName(defaultName: string = this.target?.constructor?.name) {
|
||||
return this.getClassName(Stage.Deserialize, defaultName)
|
||||
}
|
||||
|
||||
private applyPropertyCase(stage: Stage, property: string) {
|
||||
if (isNumber(this.container.renameAll)) {
|
||||
return convertCase(property, this.container.renameAll)
|
||||
} else if (stage === Stage.Serialize && isNumber(this.container.renameAll?.serialize)) {
|
||||
return convertCase(property, this.container.renameAll.serialize)
|
||||
} else if (stage === Stage.Deserialize && isNumber(this.container.renameAll?.deserialize)) {
|
||||
return convertCase(property, this.container.renameAll.deserialize)
|
||||
} else {
|
||||
return property
|
||||
}
|
||||
}
|
||||
|
||||
private getPropertyName(stage: Stage, property: string) {
|
||||
const options = this.properties.get(property)
|
||||
|
||||
if (options == null) {
|
||||
return property
|
||||
} else if (isString(options.rename)) {
|
||||
return options.rename
|
||||
} else if (stage == Stage.Serialize && isString(options.rename?.serialize)) {
|
||||
return options.rename.serialize
|
||||
} else if (stage == Stage.Deserialize && isString(options.rename?.deserialize)) {
|
||||
return options.rename.deserialize
|
||||
} else {
|
||||
return property
|
||||
}
|
||||
}
|
||||
|
||||
getSerializationPropertyName(property: string) {
|
||||
const name = this.getPropertyName(Stage.Serialize, property)
|
||||
return this.applyPropertyCase(Stage.Serialize, name)
|
||||
}
|
||||
|
||||
getDeserializationPropertyName(property: string) {
|
||||
const name = this.getPropertyName(Stage.Deserialize, property)
|
||||
return this.applyPropertyCase(Stage.Deserialize, name)
|
||||
}
|
||||
|
||||
private shouldSkip(stage: Stage, property: string, value: any) {
|
||||
const options = this.properties.get(property)
|
||||
if (options == null) {
|
||||
return false
|
||||
} else if (typeof options.skip === 'boolean') {
|
||||
return options.skip
|
||||
} else if (isFunction(options.skip)) {
|
||||
return options.skip(value)
|
||||
} else if (stage === Stage.Serialize && typeof options.skip?.serialize === 'boolean') {
|
||||
return options.skip.serialize
|
||||
} else if (stage === Stage.Serialize && isFunction(options.skip?.serialize)) {
|
||||
return options.skip.serialize(value)
|
||||
} else if (stage === Stage.Deserialize && typeof options.skip?.deserialize === 'boolean') {
|
||||
return options.skip.deserialize
|
||||
} else if (stage === Stage.Deserialize && isFunction(options.skip?.deserialize)) {
|
||||
return options.skip.deserialize(value)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
shouldSerialize(property: string, value: any) {
|
||||
return !this.shouldSkip(Stage.Serialize, property, value)
|
||||
}
|
||||
|
||||
shouldDeserialize(property: string, value: any) {
|
||||
return !this.shouldSkip(Stage.Deserialize, property, value)
|
||||
}
|
||||
|
||||
defaultFor(property: string) {
|
||||
const options = this.properties.get(property)
|
||||
if (options != null && isFunction(options.default)) {
|
||||
return options.default()
|
||||
} else if (isFunction(this.container.default)) {
|
||||
return this.container.default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
119
src/ser/impl.ts
119
src/ser/impl.ts
|
@ -1,94 +1,14 @@
|
|||
export interface ISerializeObject<T> {
|
||||
serializeKey(key: string): void
|
||||
serializeValue<U>(value: U): void
|
||||
serializeEntry<U>(key: string, value: U): void
|
||||
end(): T
|
||||
}
|
||||
|
||||
export abstract class SerializeObject<T> implements ISerializeObject<T> {
|
||||
abstract serializeKey(key: string): void
|
||||
abstract serializeValue<U>(value: U): void
|
||||
abstract end(): T
|
||||
|
||||
serializeEntry<U>(key: string, value: U): void {
|
||||
this.serializeKey(key)
|
||||
this.serializeValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISerializeIterable<T> {
|
||||
serializeElement<U>(value: U): void
|
||||
end(): T
|
||||
}
|
||||
|
||||
export abstract class SerializeIterable<T> implements ISerializeIterable<T> {
|
||||
abstract serializeElement<U>(value: U): void
|
||||
abstract end(): T
|
||||
}
|
||||
|
||||
export interface ISerializer<T> {
|
||||
serializeAny(value: any): T
|
||||
serializeBoolean(value: boolean): T
|
||||
serializeNumber(value: number): T
|
||||
serializeBigInt(value: bigint): T
|
||||
serializeString(value: string): T
|
||||
serializeSymbol(value: symbol): T
|
||||
serializeNull(): T
|
||||
serializeObject(): ISerializeObject<T>
|
||||
serializeClass(name: string): ISerializeObject<T>
|
||||
}
|
||||
|
||||
export class Serializer<T> implements ISerializer<T> {
|
||||
serializeAny(_value: any): T {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
serializeBoolean(_value: boolean): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeNumber(_value: number): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeBigInt(_value: bigint): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeString(_value: string): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeSymbol(_value: symbol): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeNull(): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeObject(): ISerializeObject<T> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeClass(_name: string): ISerializeObject<T> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
}
|
||||
|
||||
export interface Serialize<T> {
|
||||
<U, S extends Serializer<U>>(serializer: S, value: T): U
|
||||
}
|
||||
|
||||
const isPlainObject = (value: any): value is object => value?.constructor === Object
|
||||
import { SerdeOptions } from './decorator'
|
||||
import { ISerializeObject, Serializer } from './interface'
|
||||
import { isPlainObject, Nullable } from '../utils'
|
||||
|
||||
class UnhandledTypeError extends TypeError {
|
||||
constructor(serializer: Serializer<unknown>, value: any) {
|
||||
super(`unhandled type: "${typeof value}" for serializer ${serializer.constructor.name}`)
|
||||
super(`unhandled type: '${typeof value}' for serializer ${serializer.constructor.name}`)
|
||||
}
|
||||
}
|
||||
|
||||
function serializeObject<T, V extends object, S extends ISerializeObject<T>>(serializer: S, obj: V): T {
|
||||
function serializeObject<T, V extends object, S extends ISerializeObject<T>>(serializer: S, obj: V, options?: SerdeOptions): T {
|
||||
for (const key in obj) {
|
||||
serializer.serializeEntry(key, obj[key])
|
||||
}
|
||||
|
@ -96,25 +16,30 @@ function serializeObject<T, V extends object, S extends ISerializeObject<T>>(ser
|
|||
return serializer.end()
|
||||
}
|
||||
|
||||
function serializeClass<T, V extends object, S extends Serializer<T>>(serializer: S, value: V): T {
|
||||
function serializeClass<T, V extends object, S extends Serializer<T>>(serializer: S, value: V, options?: SerdeOptions): T {
|
||||
const name = value.constructor.name
|
||||
const ser = serializer.serializeClass(name)
|
||||
return serializeObject(ser, value)
|
||||
return serializeObject(ser, value, options)
|
||||
}
|
||||
|
||||
export function serialize<T, V, S extends Serializer<T>>(serializer: S, value: V): T {
|
||||
const defaultGetter = (value: any): Nullable<SerdeOptions> => {
|
||||
return value[Symbol.metadata]?.serde
|
||||
}
|
||||
|
||||
export function serialize<T, V, S extends Serializer<T>>(serializer: S, value: V, optionsGetter: (value: V) => Nullable<SerdeOptions> = defaultGetter): T {
|
||||
switch (typeof value) {
|
||||
case "string": return serializer.serializeString(value)
|
||||
case "number": return serializer.serializeNumber(value)
|
||||
case "bigint": return serializer.serializeBigInt(value)
|
||||
case "boolean": return serializer.serializeBoolean(value)
|
||||
case "symbol": return serializer.serializeSymbol(value)
|
||||
case "undefined": return serializer.serializeNull()
|
||||
case "object":
|
||||
case 'string': return serializer.serializeString(value)
|
||||
case 'number': return serializer.serializeNumber(value)
|
||||
case 'bigint': return serializer.serializeBigInt(value)
|
||||
case 'boolean': return serializer.serializeBoolean(value)
|
||||
case 'symbol': return serializer.serializeSymbol(value)
|
||||
case 'undefined': return serializer.serializeNull()
|
||||
case 'object':
|
||||
const options = optionsGetter(value)
|
||||
switch (true) {
|
||||
case value == null: return serializer.serializeNull()
|
||||
case !isPlainObject(value): return serializeClass(serializer, value)
|
||||
default: return serializeObject(serializer.serializeObject(), value)
|
||||
case !isPlainObject(value): return serializeClass(serializer, value, options)
|
||||
default: return serializeObject(serializer.serializeObject(), value, options)
|
||||
}
|
||||
default: throw new UnhandledTypeError(serializer, value)
|
||||
}
|
||||
|
|
3
src/ser/index.ts
Normal file
3
src/ser/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * from './impl'
|
||||
export * from './interface'
|
||||
|
82
src/ser/interface.ts
Normal file
82
src/ser/interface.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
export interface ISerializeObject<T> {
|
||||
serializeKey(key: string): void
|
||||
serializeValue<U>(value: U): void
|
||||
serializeEntry<U>(key: string, value: U): void
|
||||
end(): T
|
||||
}
|
||||
|
||||
export abstract class SerializeObject<T> implements ISerializeObject<T> {
|
||||
abstract serializeKey(key: string): void
|
||||
abstract serializeValue<U>(value: U): void
|
||||
abstract end(): T
|
||||
|
||||
serializeEntry<U>(key: string, value: U): void {
|
||||
this.serializeKey(key)
|
||||
this.serializeValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISerializeIterable<T> {
|
||||
serializeElement<U>(value: U): void
|
||||
end(): T
|
||||
}
|
||||
|
||||
export abstract class SerializeIterable<T> implements ISerializeIterable<T> {
|
||||
abstract serializeElement<U>(value: U): void
|
||||
abstract end(): T
|
||||
}
|
||||
|
||||
export interface ISerializer<T> {
|
||||
serializeAny(value: any): T
|
||||
serializeBoolean(value: boolean): T
|
||||
serializeNumber(value: number): T
|
||||
serializeBigInt(value: bigint): T
|
||||
serializeString(value: string): T
|
||||
serializeSymbol(value: symbol): T
|
||||
serializeNull(): T
|
||||
serializeObject(): ISerializeObject<T>
|
||||
serializeClass(name: string): ISerializeObject<T>
|
||||
}
|
||||
|
||||
export class Serializer<T> implements ISerializer<T> {
|
||||
serializeAny(_value: any): T {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
serializeBoolean(_value: boolean): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeNumber(_value: number): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeBigInt(_value: bigint): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeString(_value: string): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeSymbol(_value: symbol): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeNull(): T {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeObject(): ISerializeObject<T> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
serializeClass(_name: string): ISerializeObject<T> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
}
|
||||
|
||||
export interface Serialize<T> {
|
||||
<U, S extends Serializer<U>>(serializer: S, value: T): U
|
||||
}
|
||||
|
10
src/utils.ts
10
src/utils.ts
|
@ -36,3 +36,13 @@ export function isNumber(value: any): value is number {
|
|||
|
||||
export type Constructor<T = any> = new (...args: any[]) => T
|
||||
|
||||
export class IterResult {
|
||||
static Next<T>(value: T): IteratorResult<T> {
|
||||
return { done: false, value }
|
||||
}
|
||||
|
||||
static Done<T>(): IteratorResult<T> {
|
||||
return { done: true, value: undefined }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue