Skip to content

Commit 41367c8

Browse files
authoredFeb 4, 2022
BoolArrays and updated README.md (#15)
* fix `type`, `length`, and `digits` bug Added a function (`isSpecialType`) to aid in recognizing special types from normal objects. * Fix indentation. * Add information about what `digits` does * Add BoolArrays Added BoolArrays, potential in the future to have some sort of schema (i.e. to be BoolObjects).
1 parent 3845126 commit 41367c8

9 files changed

+93
-23
lines changed
 

‎README.md

+8
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ import { uint8, int16, uint16, int64, string8 } from '@geckos.io/typed-array-buf
5757

5858
const playerSchema = BufferSchema.schema('player', {
5959
id: uint8,
60+
// The length parameter controls the length of a String8 or String16
6061
name: { type: string8, length: 6 },
62+
// The digits parameter controls where the decimal point is placed
63+
// Therefore, it divides the maximum and minimum values by 10^n
6164
x: { type: int16, digits: 2 },
6265
y: { type: int16, digits: 2 }
6366
})
@@ -171,4 +174,9 @@ export const float64 = { _type: 'Float64Array', _bytes: 8 }
171174
export const string8 = { _type: 'String8', _bytes: 1 }
172175
/** 2 bytes per character */
173176
export const string16 = { _type: 'String16', _bytes: 2 }
177+
178+
/** An array of 7 booleans */
179+
export const bool8 = { _type: 'BitArray8', _bytes: 1 }
180+
/** An array of 15 booleans */
181+
export const bool16 = { _type: 'BitArray16', _bytes: 2 }
174182
```

‎src/deep-sort-object.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import { isPlainObject } from 'is-plain-object'
1414

15-
const isPlainArray = (arr: any) => Array.isArray(arr)
15+
const isPlainArray = (arr: any) => Array.isArray(arr) && (arr.length > 0 ? typeof arr[0] == "object" : true)
1616

1717
const isValue = (val: any) => !isPlainObject(val) && !isPlainArray(val)
1818

‎src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export { Lib as BufferSchema } from './lib'
22
export { Model } from './model'
3-
export { int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, string8, string16 } from './views'
3+
export { int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, string8, string16, bool8, bool16 } from './views'

‎src/schema.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class Schema {
2121
}
2222

2323
private isSpecialType(prop: object) {
24-
let propKeys = Object.keys(prop).filter(k => k != "type" && k != "digits" && k != "length")
24+
let propKeys = Object.keys(prop).filter(k => k != 'type' && k != 'digits' && k != 'length')
2525

2626
return !propKeys.length
2727
}

‎src/serialize.ts

+47-8
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,27 @@ export class Serialize {
2121
}
2222

2323
private isSpecialType(prop: object) {
24-
let propKeys = Object.keys(prop).filter(k => k != "type" && k != "digits" && k != "length")
24+
let propKeys = Object.keys(prop).filter(k => k != 'type' && k != 'digits' && k != 'length')
2525

2626
return !propKeys.length
2727
}
2828

29+
private boolArrayToInt(array: any) {
30+
// start with 1 to avoid errors such as 010 -> 10
31+
// now it will be 1010 which will not simplify
32+
let string = '1'
33+
for (var i = 0; i < array.length; i++) {
34+
string += +(!!array[i])
35+
}
36+
return parseInt(string, 2)
37+
}
38+
39+
private intToBoolArray(int: number) {
40+
// convert string to array, map the numbers to bools,
41+
// and remove the initial 1
42+
return [...(int >>> 0).toString(2)].map(e=> e == '0' ? false : true).slice(1)
43+
}
44+
2945
public flatten(schema: any, data: any) {
3046
let flat: any[] = []
3147

@@ -43,12 +59,19 @@ export class Serialize {
4359
// console.log('-------')
4460
// console.log('data', typeof data, data)
4561

46-
for (let property in data) {
62+
let property: any
63+
for (property in data) {
4764
if (data.hasOwnProperty(property)) {
4865
if (typeof data[property] === 'object') {
4966
// if data is array, but schemas is flat, use index 0 on the next iteration
50-
if (Array.isArray(data)) flatten(schema, data[parseInt(property)])
51-
else flatten(schema[property], data[property])
67+
if (Array.isArray(data)) {
68+
flatten(schema, data[parseInt(property)])
69+
} else if (schema[property]?._type === "BitArray8" || schema[property]?._type === "BitArray16") {
70+
flat.push({
71+
d: this.boolArrayToInt(data[property]),
72+
t: schema[property]._type
73+
})
74+
} else flatten(schema[property], data[property])
5275
}
5376
//---
5477
else {
@@ -64,11 +87,13 @@ export class Serialize {
6487
}
6588
flat.push({ d: data[property], t: schema[property].type._type })
6689
} else {
67-
// crop strings to default length of 12 characters if nothing else is specified
68-
if (schema[property]._type === 'String8' || schema[property]._type === 'String16') {
69-
data[property] = this.cropString(data[property], 12)
90+
if (schema[property]?._type) {
91+
// crop strings to default length of 12 characters if nothing else is specified
92+
if (schema[property]?._type === 'String8' || schema[property]?._type === 'String16') {
93+
data[property] = this.cropString(data[property], 12)
94+
}
95+
flat.push({ d: data[property], t: schema[property]._type })
7096
}
71-
flat.push({ d: data[property], t: schema[property]._type })
7297
}
7398
}
7499
} else {
@@ -133,6 +158,12 @@ export class Serialize {
133158
} else if (f.t === 'Float64Array') {
134159
this._dataView.setFloat64(this._bytes, f.d)
135160
this._bytes += 8
161+
} else if (f.t === 'BitArray8') {
162+
this._dataView.setUint8(this._bytes, f.d)
163+
this._bytes++
164+
} else if (f.t === 'BitArray16') {
165+
this._dataView.setUint16(this._bytes, f.d)
166+
this._bytes += 2
136167
} else {
137168
console.log('ERROR: Something unexpected happened!')
138169
}
@@ -271,6 +302,14 @@ export class Serialize {
271302
value = view.getFloat64(bytes)
272303
bytes += _bytes
273304
}
305+
if (_type === 'BitArray8') {
306+
value = this.intToBoolArray(view.getUint8(bytes))
307+
bytes += _bytes
308+
}
309+
if (_type === 'BitArray16') {
310+
value = this.intToBoolArray(view.getUint16(bytes))
311+
bytes += _bytes
312+
}
274313

275314
// apply special types options
276315
if (typeof value === 'number' && specialTypes?.digits) {

‎src/views.ts

+5
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ export const float64 = { _type: 'Float64Array', _bytes: 8 }
3030
export const string8 = { _type: 'String8', _bytes: 1 }
3131
/** 2 bytes per character */
3232
export const string16 = { _type: 'String16', _bytes: 2 }
33+
34+
/** An array of 7 booleans */
35+
export const bool8 = { _type: 'BitArray8', _bytes: 1 }
36+
/** An array of 15 booleans */
37+
export const bool16 = { _type: 'BitArray16', _bytes: 2 }

‎test/dataViews.test.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ const {
1212
float32,
1313
float64,
1414
string8,
15-
string16
15+
string16,
16+
bool8,
17+
bool16
1618
} = require('../lib/index.js')
1719

1820
describe('dataViews test', () => {
@@ -29,7 +31,9 @@ describe('dataViews test', () => {
2931
j: float64,
3032
k: string8,
3133
kk: { type: string8, length: 24 },
32-
l: string16
34+
l: string16,
35+
m: bool8,
36+
n: bool16
3337
})
3438

3539
const snapshotSchema = BufferSchema.schema('snapshot', {
@@ -55,7 +59,9 @@ describe('dataViews test', () => {
5559
j: 1.123456789,
5660
k: 'This line is too long.',
5761
kk: 'This line is too long.',
58-
l: 'Эта строка слишком длинная.'
62+
l: 'Эта строка слишком длинная.',
63+
m: [true, false, false],
64+
n: [true, true, false, true, true, true, false, false, false, true]
5965
}
6066
]
6167
}
@@ -67,6 +73,8 @@ describe('dataViews test', () => {
6773
buffer = SnapshotModel.toBuffer(data)
6874
data = SnapshotModel.fromBuffer(buffer)
6975

76+
expect(data.players[0].m[2]).toBe(false)
77+
expect(data.players[0].n[7]).toBe(false)
7078
expect(data.players[0].g).toBe(now)
7179
expect(data.players[0].h).toBe(now)
7280
expect(data.players[0].k).toBe('This line is')

‎test/serializeDeserialize.test.js

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1-
const { BufferSchema, Model, uint8, uint32, string8, int16 } = require('../lib/index.js')
1+
const { BufferSchema, Model, uint8, uint32, string8, int16, bool8 } = require('../lib/index.js')
22

33
// see: https://github.com/geckosio/typed-array-buffer-schema/issues/7
44
describe('serialize deserialize', () => {
55
const movementSchema = BufferSchema.schema('movement', {
66
sequenceNumber: uint32,
77
horizontal: uint8,
8-
vertical: uint8
8+
vertical: uint8,
9+
options: bool8
910
})
1011
const movementModel = new Model(movementSchema)
1112

1213
const inOrder = {
1314
sequenceNumber: 2,
1415
horizontal: 4,
15-
vertical: 4
16+
vertical: 4,
17+
options: [false, true, false]
1618
}
1719
const notInOrder = {
1820
horizontal: 4,
21+
options: [false, true, false],
1922
vertical: 4,
2023
sequenceNumber: 2
2124
}
@@ -27,6 +30,7 @@ describe('serialize deserialize', () => {
2730
expect(deserialized.sequenceNumber).toBe(2)
2831
expect(deserialized.horizontal).toBe(4)
2932
expect(deserialized.vertical).toBe(4)
33+
expect(deserialized.options[1]).toBe(true)
3034
})
3135

3236
it('should work if NOT defined in order', () => {
@@ -36,6 +40,7 @@ describe('serialize deserialize', () => {
3640
expect(deserialized.sequenceNumber).toBe(2)
3741
expect(deserialized.horizontal).toBe(4)
3842
expect(deserialized.vertical).toBe(4)
43+
expect(deserialized.options[1]).toBe(true)
3944
})
4045
})
4146

@@ -60,7 +65,8 @@ describe('serialize deserialize (complex)', () => {
6065
players: [playerSchema],
6166
time: uint32,
6267
stats: TimerSchema,
63-
castles: [castleSchema]
68+
castles: [castleSchema],
69+
config: bool8
6470
})
6571

6672
const gameModel = new Model(gameSchema)
@@ -79,7 +85,8 @@ describe('serialize deserialize (complex)', () => {
7985
players: [
8086
{ id: 25, x: 788, y: -14 },
8187
{ x: 1, y: 2, id: 87 }
82-
]
88+
],
89+
config: [true, false, true, true, true]
8390
}
8491

8592
it('should work if defined randomly', () => {
@@ -92,5 +99,6 @@ describe('serialize deserialize (complex)', () => {
9299
expect(deserialized.name.trim()).toBe('myGame')
93100
expect(deserialized.time).toBe(timeInSeconds)
94101
expect(deserialized.stats.time).toBe(timeInSeconds)
102+
expect(deserialized.config[1]).toBe(false)
95103
})
96104
})

‎test/simple.test.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { BufferSchema, Model, uint8, int16, uint16, string8 } = require('../lib/index.js')
1+
const { BufferSchema, Model, uint8, int16, uint16, string8, bool8 } = require('../lib/index.js')
22

33
describe('simple test', () => {
44
const castleSchema = BufferSchema.schema('castle', {
@@ -22,7 +22,8 @@ describe('simple test', () => {
2222
const snapshotSchema = BufferSchema.schema('snapshot', {
2323
time: uint16,
2424
single: uint8,
25-
data: { list: [listSchema], players: [playerSchema], castles: [castleSchema] }
25+
data: { list: [listSchema], players: [playerSchema], castles: [castleSchema] },
26+
serverConfig: bool8
2627
})
2728

2829
const SnapshotModel = new Model(snapshotSchema)
@@ -51,7 +52,8 @@ describe('simple test', () => {
5152
y: -14
5253
}
5354
]
54-
}
55+
},
56+
serverConfig: [true, false, true, false, false]
5557
}
5658

5759
let buffer
@@ -66,7 +68,7 @@ describe('simple test', () => {
6668
const uint8 = new Uint8Array(buffer)
6769

6870
expect(typeof buffer).toBe('object')
69-
expect(uint8.buffer.byteLength).toBe(40)
71+
expect(uint8.buffer.byteLength).toBe(41)
7072
})
7173

7274
test('should fromBuffer', () => {

0 commit comments

Comments
 (0)