Last active
September 10, 2019 16:33
-
-
Save tosuke/d959dd8b961c0d1ad533381e7d868439 to your computer and use it in GitHub Desktop.
インクリメンタルなデシリアライザ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Stack<T> { | |
private _intenal: T[] | |
private _pointer: number = -1 | |
constructor(size: number = 0) { | |
this._intenal = new Array(size) | |
} | |
get top(): T | undefined { | |
return this._intenal[this._pointer] | |
} | |
get empty(): boolean { | |
return this._pointer === -1 | |
} | |
push(value: T): void { | |
this._pointer++ | |
if (this._intenal.length > this._pointer) { | |
this._intenal[this._pointer] = value | |
} else { | |
this._intenal.push(value) | |
} | |
} | |
pop(): T | undefined { | |
return this._intenal[this._pointer--] | |
} | |
clear(): void { | |
this._pointer = -1 | |
} | |
} | |
type StackItem = | |
| { | |
type: 'ARRAY' | |
position: number | |
size: number | |
array: Array<unknown> | |
} | |
| { | |
type: 'MAP_KEY' | 'MAP_VALUE' | |
remains: number | |
key: string | null | |
map: Record<string, unknown> | |
} | |
class Deserializer { | |
private stack: Stack<StackItem> | |
private value: unknown | |
constructor(depth: number = 8) { | |
this.stack = new Stack(depth) | |
} | |
getResult(): unknown { | |
if (!this.stack.empty) throw new Error('Cannot get result when processing') | |
return this.value | |
} | |
setValue(value: unknown) { | |
this.value = value | |
let item: StackItem | undefined | |
while ((item = this.stack.top)) { | |
switch (item.type) { | |
case 'ARRAY': | |
item.array[item.position++] = this.value | |
if (item.position !== item.array.length) return | |
this.value = item.array | |
this.stack.pop() | |
continue | |
case 'MAP_KEY': | |
if (typeof this.value !== 'string') throw new Error('The type of key must be string') | |
item.key = this.value | |
item.type = 'MAP_VALUE' | |
return | |
case 'MAP_VALUE': | |
item.map[item.key!] = this.value | |
if (--item.remains !== 0) { | |
item.type = 'MAP_KEY' | |
return | |
} else { | |
this.value = item.map | |
this.stack.pop() | |
continue | |
} | |
default: | |
return | |
} | |
} | |
} | |
enterArray(size: number) { | |
this.stack.push({ type: 'ARRAY', position: 0, size: size | 0, array: new Array(size) }) | |
} | |
enterMap(size: number) { | |
if (size === 0) { | |
this.value = {} | |
return | |
} | |
this.stack.push({ type: 'MAP_KEY', remains: size | 0, key: null, map: {} }) | |
} | |
} | |
const d = new Deserializer() | |
d.enterMap(4) | |
d.setValue('id') | |
d.setValue(1) | |
d.setValue('text') | |
d.setValue('hogehoge') | |
d.setValue('user') | |
d.enterMap(2) | |
d.setValue('id') | |
d.setValue(1) | |
d.setValue('name') | |
d.setValue('admin') | |
d.setValue('array') | |
d.enterArray(3) | |
d.setValue(1) | |
d.setValue(2) | |
d.setValue(3) | |
console.log(d.getResult()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
yea