Compare commits

..

No commits in common. "0b100c5b9e95af6a33db0c4a29635973df00c746" and "981e74c3ccc4b1282d5683816488defbb501d7bd" have entirely different histories.

5 changed files with 72 additions and 1124 deletions

1015
dist/test.js vendored

File diff suppressed because it is too large Load diff

View file

@ -2,10 +2,10 @@
"name": "serde-json-ts",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"main": "index.js",
"scripts": {
"build": "esbuild src/index.ts --bundle --outfile=dist/index.js",
"build:test": "esbuild test.ts --format=cjs --bundle --target=es2022 --outfile=dist/test.js --tsconfig=tsconfig.json",
"build:test": "esbuild test.ts --platform=node --target=es2022 --bundle --outfile=dist/test.js --tsconfig=tsconfig.json",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],

138
src/de.ts
View file

@ -1,6 +1,6 @@
import { IIterableAccess, MapAccess, IVisitor, IDeserializer, IterResult, Deserialize, GenericVisitor, GenericSeed } from 'serde/de'
import { DefaultIterableAccessImpl, DefaultMapAccessImpl, Deserialize, Deserializer, GenericVisitor, IterableAccess, MapAccess, Visitor } from 'serde/de'
import { mixin, Nullable } from 'serde/utils'
import { unexpected } from './err'
import { GlobalRegistry, Registry } from 'serde'
type Byte = number
@ -44,24 +44,20 @@ const Token = Object.freeze({
Colon: char`:`
} as const)
export class CommaSeparated<T> extends MapAccess implements IIterableAccess {
export interface CommaSeparated extends MapAccess, IterableAccess { }
@mixin<MapAccess>(DefaultMapAccessImpl)
@mixin<IterableAccess>(DefaultIterableAccessImpl)
export class CommaSeparated implements MapAccess, IterableAccess {
private readonly de: JSONDeserializer
private readonly defaultSeed: GenericSeed<T>
private first: boolean = true
constructor(deserializer: JSONDeserializer, visitor: IVisitor<T> = new GenericVisitor()) {
super()
constructor(deserializer: JSONDeserializer) {
this.de = deserializer
this.defaultSeed = new GenericSeed(visitor)
}
private seed(): Deserialize {
return this.defaultSeed.deserialize.bind(this.defaultSeed) as Deserialize
}
private nextItemSeed<T, D extends Deserialize>(seed: D, end: number): IteratorResult<T> {
if (this.de.buffer.peek().next() === end) {
return IterResult.Done()
nextKeySeed<T, K extends Deserialize<T>>(seed: K): Nullable<T> {
if (this.de.buffer.peek().next() === Token.RightCurly) {
return
}
if (!this.first) {
@ -72,47 +68,42 @@ export class CommaSeparated<T> extends MapAccess implements IIterableAccess {
}
this.first = false
return IterResult.Next(seed(this.de)) as IteratorResult<T>
return seed.deserialize(this.de)
}
nextKeySeed<T, K extends Deserialize>(seed: K): IteratorResult<T> {
return this.nextItemSeed(seed, Token.RightCurly)
}
nextValueSeed<T, V extends Deserialize>(seed: V): IteratorResult<T> {
nextValueSeed<T, V extends Deserialize<T>>(seed: V): Nullable<T> {
const next = this.de.buffer.next()
if (next !== Token.Colon) {
throw unexpected(':', String.fromCharCode(next), this.de.buffer.position)
console.log(this.de.buffer.toString())
throw unexpected(':', next.toString(), this.de.buffer.position)
}
return IterResult.Next(seed(this.de)) as IteratorResult<T>
return seed.deserialize(this.de)
}
private nextItem<T>(end: number): IteratorResult<T> {
return this.nextItemSeed(this.seed(), end)
}
nextElementSeed<T, I extends Deserialize<T>>(seed: I): Nullable<T> {
if (this.de.buffer.peek().next() === Token.RightSquare) {
return
}
nextKey<T>(): IteratorResult<T> {
return this.nextItem(Token.RightCurly)
}
if (!this.first) {
const take = this.de.buffer.take()
if (take.next() !== Token.Comma) {
throw unexpected(',', take.toString(), this.de.buffer.position)
}
}
nextValue<V>(): IteratorResult<V> {
return this.nextValueSeed(this.seed())
}
nextElement<T>(): IteratorResult<T> {
return this.nextItem(Token.RightSquare)
this.first = false
return seed.deserialize(this.de)
}
}
class ByteArray {
class StringBuffer {
private readonly view: Uint8Array
private index: number = 0
private readonly encoder: TextEncoder
private readonly decoder: TextDecoder
private index: number = 0
get position() {
return this.index
}
@ -127,11 +118,11 @@ class ByteArray {
this.decoder = decoder
}
static fromArrayBuffer(value: ArrayBuffer, encoder?: TextEncoder, decoder?: TextDecoder): ByteArray {
static fromArrayBuffer(value: ArrayBuffer, encoder?: TextEncoder, decoder?: TextDecoder): StringBuffer {
return new this(new Uint8Array(value), encoder, decoder)
}
static fromString(value: string, encoder: TextEncoder = new TextEncoder(), decoder?: TextDecoder): ByteArray {
static fromString(value: string, encoder: TextEncoder = new TextEncoder(), decoder?: TextDecoder): StringBuffer {
return this.fromArrayBuffer(
encoder.encode(value),
encoder,
@ -161,7 +152,7 @@ class ByteArray {
return this.decoder.decode(this.toBytes())
}
take(limit: number = 1): ByteArray {
take(limit: number = 1): StringBuffer {
const bytes = this.peek(limit)
this.index += limit
return bytes
@ -171,7 +162,7 @@ class ByteArray {
return this.view[this.index + index]
}
takeWhile(fn: Predicate<number>): ByteArray {
takeWhile(fn: Predicate<number>): StringBuffer {
let index = 0
while (!this.done() && fn(this.at(index))) {
@ -181,30 +172,12 @@ class ByteArray {
return this.take(index)
}
takeUntil(fn: Predicate<number>): ByteArray {
return this.takeWhile((v: number) => !fn(v))
}
drop(limit: number) {
this.index += limit
return this
}
dropWhile(fn: Predicate<number>): ByteArray {
let index = 0
while (!this.done() && fn(this.at(index))) {
index += 1
}
return this.drop(index)
}
dropUntil(fn: Predicate<number>): ByteArray {
return this.dropWhile((v: number) => !fn(v))
}
peek(limit: number = 1): ByteArray {
peek(limit: number = 1): StringBuffer {
const index = this.index
return this.slice(index, index + limit)
}
@ -221,7 +194,7 @@ class ByteArray {
}
slice(start?: number, end?: number) {
return new ByteArray(
return new StringBuffer(
this.view.subarray(start, end),
this.encoder,
this.decoder
@ -243,20 +216,18 @@ class ByteArray {
}
}
export class JSONDeserializer implements IDeserializer {
readonly buffer: ByteArray
readonly registry: Registry
export class JSONDeserializer implements Deserializer {
readonly buffer: StringBuffer
constructor(buffer: ByteArray, registry: Registry = GlobalRegistry) {
constructor(buffer: StringBuffer) {
this.buffer = buffer
this.registry = registry
}
static fromString(value: string): JSONDeserializer {
return new this(ByteArray.fromString(value))
return new this(StringBuffer.fromString(value))
}
deserializeAny<T>(visitor: IVisitor<T>): T {
deserializeAny<T, V extends Visitor<T>>(visitor: V): T {
const peek = this.buffer.peek()
const nextByte = peek.take()
const byte = nextByte.next()
@ -279,7 +250,7 @@ export class JSONDeserializer implements IDeserializer {
}
}
deserializeNull<T, V extends IVisitor<T>>(visitor: V): T {
deserializeNull<T, V extends Visitor<T>>(visitor: V): T {
if (this.buffer.startsWith('null')) {
this.buffer.take(4)
}
@ -287,11 +258,11 @@ export class JSONDeserializer implements IDeserializer {
return visitor.visitNull()
}
deserializeObject<T, V extends IVisitor<T>>(visitor: V): T {
private _deserializeObject<T>(fn: (value: CommaSeparated) => T): T {
let next = this.buffer.take()
if (next.next() === Token.LeftCurly) {
const value = visitor.visitObject(new CommaSeparated(this))
const value = fn(new CommaSeparated(this))
next = this.buffer.take()
if (next.next() === Token.RightCurly) {
@ -304,11 +275,11 @@ export class JSONDeserializer implements IDeserializer {
}
}
deserializeClass<T, V extends IVisitor<T>>(_name: string, visitor: V): T {
return this.deserializeObject(visitor)
deserializeObject<T, V extends Visitor<T>>(visitor: V): T {
return this._deserializeObject(visitor.visitObject.bind(visitor))
}
deserializeString<T, V extends IVisitor<T>>(visitor: V): T {
deserializeString<T, V extends Visitor<T>>(visitor: V): T {
const next = this.buffer.take()
if (next.next() === Token.Quote) {
let index = -1
@ -329,7 +300,7 @@ export class JSONDeserializer implements IDeserializer {
}
}
deserializeNumber<T, V extends IVisitor<T>>(visitor: V): T {
deserializeNumber<T, V extends Visitor<T>>(visitor: V): T {
const next = this.buffer.peek().next()
if (isNumericToken(next)) {
@ -346,11 +317,11 @@ export class JSONDeserializer implements IDeserializer {
throw unexpected('"-", ".", or 0..=9', next.toString(), this.buffer.position)
}
deserializeBigInt<T, V extends IVisitor<T>>(visitor: V): T {
deserializeBigInt<T, V extends Visitor<T>>(visitor: V): T {
return this.deserializeNumber(visitor)
}
deserializeBoolean<T, V extends IVisitor<T>>(visitor: V): T {
deserializeBoolean<T, V extends Visitor<T>>(visitor: V): T {
const next = this.buffer.next()
let length = 3
@ -367,15 +338,15 @@ export class JSONDeserializer implements IDeserializer {
return visitor.visitBoolean(length === 3)
}
deserializeSymbol<T, V extends IVisitor<T>>(_visitor: V): T {
deserializeSymbol<T, V extends Visitor<T>>(_visitor: V): T {
throw new Error('Method not implemented.')
}
deserializeIterable<T, V extends IVisitor<T>>(visitor: V): T {
deserializeIterable<T, V extends Visitor<T>>(visitor: V): T {
let next = this.buffer.take()
if (next.next() === Token.LeftSquare) {
const value = visitor.visitIterable(new CommaSeparated(this))
const value = visitor.visitIterable!(new CommaSeparated(this))
next = this.buffer.take()
if (next.next() === Token.RightSquare) {
@ -387,10 +358,5 @@ export class JSONDeserializer implements IDeserializer {
throw unexpected('[', next.toString(), this.buffer.position)
}
}
deserializeFunction<T, V extends IVisitor<T>>(_visitor: V): T {
throw new Error('Method not implemented.')
}
}

View file

@ -1,16 +1,16 @@
import { serializeWith } from 'serde/ser'
import { Deserialize } from 'serde/de'
import { JSONSerializer } from './ser'
import { deserialize, Deserialize } from 'serde/de'
import { JSONDeserializer } from './de'
import { serialize } from 'serde/ser'
export function toString(value: any): string {
const serializer = new JSONSerializer()
serialize(serializer, value)
serializeWith(serializer, value)
return serializer.output
}
export function fromString<T, D extends Deserialize<T>>(value: string, into: D): T {
const deserializer = JSONDeserializer.fromString(value)
return deserialize(deserializer, into)
return into.deserialize(deserializer)
}

View file

@ -1,28 +1,29 @@
import { ISerializeIterable, ISerializeObject, ISerializer, serialize, SerializeObject } from "serde/ser"
import { IterableSerializer, ObjectSerializer, Serializable, Serializer, serializeWith } from 'serde/ser'
class JSONObjectSerializer extends SerializeObject<void> {
const Identifier = (value: string) => `\x02${value}\x04`
class JSONObjectSerializer implements ObjectSerializer<void> {
private ser: JSONSerializer
private first: boolean = true
constructor(serializer: JSONSerializer) {
super()
this.ser = serializer
serializer.write('{')
}
serializeKey<U>(key: U): void {
serializeKey<U extends Serializable>(key: U): void {
if (!this.first) {
this.ser.write(',')
} else {
this.first = false
}
serialize(this.ser, key)
serializeWith(this.ser, key)
this.ser.write(':')
}
serializeValue<U>(value: U): void {
serialize(this.ser, value)
serializeValue<U extends Serializable>(value: U): void {
serializeWith(this.ser, value)
}
end(): void {
@ -30,7 +31,7 @@ class JSONObjectSerializer extends SerializeObject<void> {
}
}
class JSONIterableSerializer implements ISerializeIterable<void> {
class JSONIterableSerializer implements IterableSerializer<void> {
private ser: JSONSerializer
private first: boolean = true
@ -39,14 +40,14 @@ class JSONIterableSerializer implements ISerializeIterable<void> {
serializer.write('[')
}
serializeElement<U>(element: U): void {
serializeElement<U extends Serializable>(element: U): void {
if (!this.first) {
this.ser.write(',')
} else {
this.first = false
}
serialize(this.ser, element)
serializeWith(this.ser, element)
}
end(): void {
@ -54,7 +55,7 @@ class JSONIterableSerializer implements ISerializeIterable<void> {
}
}
export class JSONSerializer implements ISerializer<void> {
export class JSONSerializer implements Serializer<void> {
output: string = ''
write(value: string) {
@ -78,14 +79,10 @@ export class JSONSerializer implements ISerializer<void> {
}
}
serializeObject(): ISerializeObject<void> {
serializeObject(): ObjectSerializer<void> {
return new JSONObjectSerializer(this)
}
serializeClass(_name: PropertyKey): ISerializeObject<void> {
return this.serializeObject()
}
serializeNumber(value: number) {
this.write(value.toString())
}
@ -94,7 +91,7 @@ export class JSONSerializer implements ISerializer<void> {
this.write(value.toString())
}
serializeIterable(): ISerializeIterable<void> {
serializeIterable(): IterableSerializer<void> {
return new JSONIterableSerializer(this)
}