Skip to content

Commit

Permalink
Implement ser/des iterable
Browse files Browse the repository at this point in the history
  • Loading branch information
allevo committed Nov 13, 2023
1 parent 43ef57f commit 62faace
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 10 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ This library exports the following functions:
- `ser.serializeString(string)`: serializes a string.
- `des.deserializeString()`: deserializes a string.
- `ser.serializeArray(array, (ser, item) => { ... })`: serializes an array.
- `des.deserializeArray(array, (des) => { ... })`: deserializes an array.
- `des.deserializeArray((des) => { ... })`: deserializes an array.
- `ser.serializeIterable(iterable, (ser, item) => { ... })`: serializes an iterable.
- `des.deserializeIterable((des) => { ... })`: deserializes an iterable.
- `ser.serializeFloat32(float32)`: serializes float 32bit.
- `des.deserializeFloat32()`: deserializes float 32bit.
- `ser.getBuffer()`: returns the serialized buffer.
Expand Down
2 changes: 1 addition & 1 deletion examples/complex_object.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createSer, createDes } from '../src/index.js'
import type { Ser, Des } from '../src/index'
import type { Ser, Des } from '../src/index.js'

interface User {
id: number
Expand Down
26 changes: 26 additions & 0 deletions examples/iterable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createSer, createDes } from '../src/index.js'
import type { Ser, Des } from '../src/index.js'

let buffer

{ // Serialize
const map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three']
])
const ser: Ser = createSer()
ser.serializeIterable(map, (ser, [k, v]) => {
ser.serializeUInt32(k)
ser.serializeString(v)
})
buffer = ser.getBuffer()
}

{ // Deserialize
const des: Des = createDes(buffer)
const map = new Map(des.deserializeIterable((des) => {
return [des.deserializeUInt32(), des.deserializeString()]
}))
console.log(map)
}
2 changes: 1 addition & 1 deletion examples/object.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createSer, createDes } from '../src/index.js'
import type { Ser, Des } from '../src/index'
import type { Ser, Des } from '../src/index.js'

interface Todo {
id: number
Expand Down
2 changes: 1 addition & 1 deletion examples/simple.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createSer, createDes } from '../src/index.js'
import type { Ser, Des } from '../src/index'
import type { Ser, Des } from '../src/index.js'

const ser: Ser = createSer()

Expand Down
2 changes: 1 addition & 1 deletion examples/todos.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createSer, createDes } from '../src/index.js'
import type { Ser, Des } from '../src/index'
import type { Ser, Des } from '../src/index.js'

let buffer

Expand Down
33 changes: 32 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface Ser {
serializeFloat32: (n: number) => void
serializeString: (str: string) => void
serializeArray: <T>(arr: T[], serialize: (ser: Ser, t: T) => void) => void
serializeIterable <T>(iterable: Iterable<T>, serialize: (ser: Ser, t: T) => void): void
}
export interface Des {
index: number
Expand All @@ -22,6 +23,7 @@ export interface Des {
deserializeFloat32: () => number
deserializeString: () => string
deserializeArray: <T>(deserialize: (des: Des) => T) => T[]
deserializeIterable <T>(deserialize: (des: Des) => T): Iterable<T>
}

export function createSer (): Ser {
Expand All @@ -36,6 +38,7 @@ export function createSer (): Ser {
serializeFloat32,
serializeString,
serializeArray,
serializeIterable,
getBuffer: function () { return this.buffer.slice(0, this.index * 4) }
}
}
Expand All @@ -59,7 +62,8 @@ export function createDes (buffer: ArrayBuffer): Des {
deserializeUInt32,
deserializeFloat32,
deserializeString,
deserializeArray
deserializeArray,
deserializeIterable,
}
}

Expand Down Expand Up @@ -113,3 +117,30 @@ function deserializeArray<T> (this: Des, deserialize: (ser: Des) => T): T[] {
}
return arr
}

function serializeIterable<T> (this: Ser, iterable: Iterable<T>, serialize: (ser: Ser, t: T) => void): void {
// Keep space for the length
const currentIndex = this.index++
let n = 0
for (const t of iterable) {
n++
serialize(this, t)
}
this.uint32Array[currentIndex] = n
}

function deserializeIterable<T> (this: Des, deserialize: (des: Des) => T): Iterable<T> {
const len = this.deserializeUInt32()
const des = this
const aGeneratorObject = (function* () {
for (let i = 0; i < len; i++) {
yield deserialize(des)
}
})();

return {
[Symbol.iterator]() {
return aGeneratorObject;
},
}
}
47 changes: 47 additions & 0 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,53 @@ await t.test('array', async t => {
})
})

await t.test('iterable', async t => {
await t.test('map<number, number>', async t => {
const expected: Map<number, number> = new Map([[0, 1], [2, 3], [4, 5]])

const ser = createSer()
ser.serializeIterable(expected.entries(), (ser, n) => {
ser.serializeUInt32(n[0])
ser.serializeUInt32(n[1])
})

const des = createDes(ser.getBuffer())
const m = new Map(des.deserializeIterable(() => [des.deserializeUInt32(), des.deserializeUInt32()]))
assert.deepStrictEqual(m, expected)
})

await t.test('map<string, number>', async t => {
const expected: Map<string, number> = new Map([
['foo', 1],
['bar', 3],
['baz', 5]
])

const ser = createSer()
ser.serializeIterable(expected.entries(), (ser, n) => {
ser.serializeString(n[0])
ser.serializeUInt32(n[1])
})

const des = createDes(ser.getBuffer())
const m = new Map(des.deserializeIterable(() => [des.deserializeString(), des.deserializeUInt32()]))
assert.deepStrictEqual(m, expected)
})

await t.test('set<number>', async t => {
const expected: Set<number> = new Set([1, 3, 5])

const ser = createSer()
ser.serializeIterable(expected.values(), (ser, n) => {
ser.serializeUInt32(n)
})

const des = createDes(ser.getBuffer())
const m = new Set(des.deserializeIterable(() => des.deserializeUInt32()))
assert.deepStrictEqual(m, expected)
})
})

await t.test('random items', async t => {
const elements: any[] = [
{ item: 'foo', serializer: 'serializeString', deserializer: 'deserializeString' },
Expand Down
10 changes: 6 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{
"compilerOptions": {
"target": "es5",
"module": "CommonJS",
"target": "es2017",
"module": "NodeNext",
"declaration": true,
"outDir": "./dist",
"moduleResolution": "nodenext",
"rootDir": "./",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
"forceConsistentCasingInFileNames": true,
"lib": ["ES2023", "dom"]
},
"include": ["src/**/*", "examples/**/*", "tests/**/*"],
"include": ["src/**/*", "examples/**/*", "tests/**/*", "tests"],
"exclude": ["node_modules"]
}

0 comments on commit 62faace

Please sign in to comment.