Skip to content

Commit d42176b

Browse files
committed
.
0 parents  commit d42176b

21 files changed

+1059
-0
lines changed

.github/FUNDING.yml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github: yandeu
2+
patreon: yannickdeubel

.github/workflows/main.yml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [10.x, 12.x, 14.x]
16+
17+
steps:
18+
- uses: actions/checkout@v2
19+
20+
- name: Use Node.js ${{ matrix.node-version }}
21+
uses: actions/setup-node@v1
22+
with:
23+
node-version: ${{ matrix.node-version }}
24+
25+
- name: npm install, build, and test
26+
run: |
27+
npm install
28+
npm run build
29+
npm test
30+
- uses: codecov/codecov-action@v1
31+
env:
32+
CI: true

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
coverage
2+
lib
3+
node_modules
4+
package-lock.json

.prettierrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "semi": false, "singleQuote": true, "trailingComma": "none" }

LICENSE

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2020, Yannick Deubel (https://github.com/yandeu)
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
3. Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<div align="center">
2+
3+
<img src="readme/logo.png" alt="logo" height="150">
4+
5+
# Typed Array Buffer Schema
6+
7+
## A Schema based Object to Buffer converter
8+
9+
#### Easily convert/compress your JavaScript Objects to Binary Data using a simple to use Schema.
10+
11+
[![NPM version](https://img.shields.io/npm/v/@geckos.io/typed-array-buffer-schema.svg?style=flat-square)](https://www.npmjs.com/package/@geckos.io/typed-array-buffer-schema)
12+
[![Github Workflow](https://img.shields.io/github/workflow/status/geckosio/typed-array-buffer-schema/CI/master?label=github%20build&logo=github&style=flat-square)](https://github.com/geckosio/typed-array-buffer-schema/actions?query=workflow%3ACI)
13+
[![GitHub last commit](https://img.shields.io/github/last-commit/geckosio/typed-array-buffer-schema?style=flat-square)](https://github.com/geckosio/typed-array-buffer-schema/commits/master)
14+
[![Downloads](https://img.shields.io/npm/dm/@geckos.io/typed-array-buffer-schema.svg?style=flat-square)](https://www.npmjs.com/package/@geckos.io/typed-array-buffer-schema)
15+
[![Codecov](https://img.shields.io/codecov/c/github/geckosio/typed-array-buffer-schema?logo=codecov&style=flat-square)](https://codecov.io/gh/geckosio/typed-array-buffer-schema)
16+
[![build with TypeScript](https://img.shields.io/badge/built%20with-TypeScript-blue?style=flat-square)](https://www.typescriptlang.org/)
17+
18+
</div>
19+
20+
---
21+
22+
## Schema
23+
24+
```js
25+
import { BufferSchema, Model, uint8, int16, uint16 } from './index'
26+
import { string8, int64 } from './views'
27+
28+
const playerSchema = BufferSchema.schema('player', {
29+
id: uint8,
30+
name: { type: string8, length: 6 },
31+
x: { type: int16, digits: 2 },
32+
y: { type: int16, digits: 2 }
33+
})
34+
35+
const towerSchema = BufferSchema.schema('tower', {
36+
id: uint8,
37+
health: uint8,
38+
team: uint8
39+
})
40+
41+
const mainSchema = BufferSchema.schema('snapshot', {
42+
time: int64,
43+
tick: uint16,
44+
players: [playerSchema],
45+
towers: [towerSchema]
46+
})
47+
48+
const gameState = {
49+
time: new Date().getTime(),
50+
tick: 32580,
51+
players: [
52+
{ id: 0, name: 'Mistin', x: -14.43, y: 47.78 },
53+
{ id: 1, name: 'Coobim', x: 21.85, y: -78.48 }
54+
],
55+
towers: [
56+
{ id: 0, health: 100, team: 0 },
57+
{ id: 1, health: 89, team: 0 },
58+
{ id: 2, health: 45, team: 1 }
59+
]
60+
}
61+
62+
const mainModel = new Model(mainSchema)
63+
const buffer = mainModel.toBuffer(gameState)
64+
const data = mainModel.fromBuffer(buffer)
65+
66+
// toBuffer() shrunk the byte size from 241 to only 56
67+
// that is -77% compression!
68+
console.log(JSON.stringify(gameState).length) // 241
69+
console.log(buffer.byteLength) // 56
70+
console.log(JSON.stringify(data).length) // 241
71+
```
72+
73+
## DataViews
74+
75+
A list of all supported dataViews
76+
77+
```js
78+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
79+
80+
/** -128 to 127 (1 byte) */
81+
export const int8 = { _type: 'Int8Array', _bytes: 1 }
82+
/** 0 to 255 (1 byte) */
83+
export const uint8 = { _type: 'Uint8Array', _bytes: 1 }
84+
85+
/** -32768 to 32767 (2 bytes) */
86+
export const int16 = { _type: 'Int16Array', _bytes: 2 }
87+
/** 0 to 65535 (2 bytes) */
88+
export const uint16 = { _type: 'Uint16Array', _bytes: 2 }
89+
90+
/** -2147483648 to 2147483647 (4 bytes) */
91+
export const int32 = { _type: 'Int32Array', _bytes: 4 }
92+
/** 0 to 4294967295 (4 bytes) */
93+
export const uint32 = { _type: 'Uint32Array', _bytes: 4 }
94+
95+
/** -2^63 to 2^63-1 (8 bytes) */
96+
export const int64 = { _type: 'BigInt64Array', _bytes: 8 }
97+
/** 0 to 2^64-1 (8 bytes) */
98+
export const uint64 = { _type: 'BigUint64Array', _bytes: 8 }
99+
100+
/** 1.2×10-38 to 3.4×1038 (7 significant digits e.g., 1.123456) (4 bytes) */
101+
export const float32 = { _type: 'Float32Array', _bytes: 4 }
102+
103+
/** 5.0×10-324 to 1.8×10308 (16 significant digits e.g., 1.123...15) (8 bytes) */
104+
export const float64 = { _type: 'Float64Array', _bytes: 8 }
105+
106+
/** 1 byte per character */
107+
export const string8 = { _type: 'String8', _bytes: 1 }
108+
/** 2 bytes per character */
109+
export const string16 = { _type: 'String16', _bytes: 2 }
110+
```

package.json

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "@geckos.io/typed-array-buffer-schema",
3+
"version": "1.0.0",
4+
"description": "A Schema based Object to Buffer converter",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "npm run dev",
8+
"dev": "npm run build && npm-run-all --parallel dev:*",
9+
"dev:tsc": "tsc --watch",
10+
"dev:nodemon": "nodemon lib/dev.js --watch lib",
11+
"build": "npm run clean && tsc",
12+
"test": "jest --collectCoverage",
13+
"clean": "rimraf lib",
14+
"format": "prettier --write src/**/*.ts",
15+
"prepublishOnly": "npm run build && npm test"
16+
},
17+
"keywords": [
18+
"typed",
19+
"array",
20+
"buffer",
21+
"serialization",
22+
"schema",
23+
"binary"
24+
],
25+
"author": "Yannick Deubel",
26+
"license": "BSD-3-Clause",
27+
"repository": {
28+
"type": "git",
29+
"url": "git://github.com/geckosio/typed-array-buffer-schema.git"
30+
},
31+
"bugs": {
32+
"url": "https://github.com/geckosio/typed-array-buffer-schema/issues"
33+
},
34+
"dependencies": {
35+
"lodash": "^4.17.15"
36+
},
37+
"devDependencies": {
38+
"@types/lodash": "^4.14.155",
39+
"jest": "^26.0.1",
40+
"nodemon": "^2.0.4",
41+
"npm-run-all": "^4.1.5",
42+
"prettier": "^2.0.5",
43+
"rimraf": "^3.0.2",
44+
"typescript": "^3.9.5"
45+
},
46+
"funding": {
47+
"url": "https://github.com/sponsors/yandeu"
48+
}
49+
}

readme/logo.png

23.6 KB
Loading

src/dev.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { BufferSchema, Model, uint8, int16, uint16 } from './index'
2+
import { string8, int64 } from './views'
3+
4+
const playerSchema = BufferSchema.schema('player', {
5+
id: uint8,
6+
name: { type: string8, length: 6 },
7+
x: { type: int16, digits: 2 },
8+
y: { type: int16, digits: 2 }
9+
})
10+
11+
const towerSchema = BufferSchema.schema('tower', {
12+
id: uint8,
13+
health: uint8,
14+
team: uint8
15+
})
16+
17+
const mainSchema = BufferSchema.schema('snapshot', {
18+
time: int64,
19+
tick: uint16,
20+
players: [playerSchema],
21+
towers: [towerSchema]
22+
})
23+
24+
const gameState = {
25+
time: new Date().getTime(),
26+
tick: 32580,
27+
players: [
28+
{ id: 0, name: 'Mistin', x: -14.43, y: 47.78 },
29+
{ id: 1, name: 'Coobim', x: 21.85, y: -78.48 }
30+
],
31+
towers: [
32+
{ id: 0, health: 100, team: 0 },
33+
{ id: 1, health: 89, team: 0 },
34+
{ id: 2, health: 45, team: 1 }
35+
]
36+
}
37+
38+
const mainModel = new Model(mainSchema)
39+
const buffer = mainModel.toBuffer(gameState)
40+
const data = mainModel.fromBuffer(buffer)
41+
42+
// toBuffer() shrunk the byte size from 241 to only 56
43+
// that is -77% compression!
44+
console.log(JSON.stringify(gameState).length) // 241
45+
console.log(buffer.byteLength) // 56
46+
console.log(JSON.stringify(data).length) // 241

src/index.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export { Lib as BufferSchema } from './lib'
2+
export { Model } from './model'
3+
export {
4+
int8,
5+
uint8,
6+
int16,
7+
uint16,
8+
int32,
9+
uint32,
10+
int64,
11+
uint64,
12+
float32,
13+
float64,
14+
string8,
15+
string16
16+
} from './views'

src/lib.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Schema } from './schema'
2+
3+
export class Lib {
4+
public static _schemas: Map<string, Schema> = new Map()
5+
6+
public static newHash(name: string, _struct: any) {
7+
// https://stackoverflow.com/a/7616484/12656855
8+
const strToHash = (s: string) => {
9+
let hash = 0
10+
11+
for (let i = 0; i < s.length; i++) {
12+
const chr = s.charCodeAt(i)
13+
hash = (hash << 5) - hash + chr
14+
hash |= 0 // Convert to 32bit integer
15+
}
16+
hash *= 254785 // times a random number
17+
return Math.abs(hash)
18+
.toString(32)
19+
.slice(2, 6)
20+
}
21+
22+
let hash = strToHash(JSON.stringify(_struct) + name)
23+
if (hash.length !== 4) throw new Error('Hash has not length of 4')
24+
return `#${hash}`
25+
}
26+
27+
public static schema(name: string, _struct: Object) {
28+
const id = Lib.newHash(name, _struct)
29+
const s = new Schema(id, name, _struct)
30+
this._schemas.set(id, s)
31+
return s
32+
}
33+
}

src/model.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Schema } from './schema'
2+
import { Serialize } from './serialize'
3+
4+
export class Model extends Serialize {
5+
constructor(protected schema: Schema) {
6+
super(schema)
7+
}
8+
}

0 commit comments

Comments
 (0)