Repository navigation
Expand file tree
/
Copy pathcodex.js
More file actions
131 lines (122 loc) · 3.85 KB
/
Copy pathcodex.js
File metadata and controls
131 lines (122 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
var LengthDelimited = require('./length-delimited')
var V = require('varstruct')
var inspect = require('util').inspect
function BufferCodec () {
function encode (value, buffer, start) {
value.copy(buffer, start)
return encode.bytes = value.length
}
function decode (buffer, start=0, _end=buffer.length) {
var value = buffer.slice(start, _end)
decode.bytes = value.length
return value
}
return {
encode, decode,
encodingLength: (value) => { return value.length }
}
}
var codex = {
u8: {
type: 'u8',
encode: (value, buffer, start) => {
if(value > 0xff || value < 0) throw new Error('u8 value out of bounds')
buffer[start] = value & 0xff
return 1
},
decode: (buffer, start) => buffer[start] & 0xff,
bytes: 1,
},
u16: {
type: 'u16',
encode: (value, buffer, start=0) => { buffer.writeUint16LE(value, start); return 2 },
decode: (buffer, start=0) => buffer.readUint16LE(start),
bytes: 2,
},
u32: {
type: 'u32',
encode: (value, buffer, start=0) => { buffer.writeUint32LE(value, start); return 4 },
decode: (buffer, start=0) => buffer.readUint32LE(start),
bytes: 4,
},
u64: {
type: 'u64',
//node buffers provide writeBigInt64LE but it's not UInt, so have to wrap that.
encode: (value, buffer, start) => {
if('number' === typeof value)
value = BigInt(value)
if(value > 0xffff_ffff_ffff_ffff || value < 0)
throw new Error('u64 out of bounds')
if(value > 0x7fff_ffff_ffff_ffff)
buffer.writeBigInt64LE(value*-1n, start)
else
buffer.writeBigInt64LE(value, start)
return 8
},
decode: (buffer, start) => {
var value = buffer.readBigInt64LE(start)
if(value < 0) return value * -1
return value
},
bytes: 8
},
f32: {
type: 'f32',
encode: (value, buffer, start=0) => { buffer.writeFloatLE(value, start); return 4 },
decode: (buffer, start=0) => buffer.readFloatLE(start),
bytes: 4,
},
f64: {
type: 'f64',
encode: (value, buffer, start=0) => {
if('number' !== typeof value) throw new Error('expected number, got:'+inspect(value))
buffer.writeDoubleLE(value, start)
return 8
},
decode: (buffer, start=0) => buffer.readDoubleLE(start),
bytes: 8,
},
buffer: BufferCodec()
//i8, i16, i32, i64 ...
}
var string = {
type: 'string',
encode: (value, buffer, start) => {
var bytes = Buffer.byteLength(value)
if('string' !== typeof value) throw new Error('expected a string, got:'+inspect(value))
buffer.write(value, start, start+bytes)
buffer[start+bytes+1] = 0
string.encode.bytes = bytes+1
},
decode: (buffer, start, end) => {
var terminal = end-1
if(buffer[terminal] != 0) {
throw new Error('invalid string termination:' +buffer[terminal]+' (0x'+buffer[terminal].toString(16)+'), at:'+(terminal-start))
}
var value = buffer.toString('utf8', start, terminal)
string.decode.bytes = end - start
return value
},
encodingLength: (value) => Buffer.byteLength(value, 'utf8') + 1
}
codex.string_u8 = LengthDelimited(0, codex.u8, string)
codex.string_u16 = LengthDelimited(0, codex.u16, string)
codex.string_u32 = LengthDelimited(0, codex.u32, string)
//codex.string_u64 = LengthDelimited(0x10, codex.64, string)
codex.buffer_u8 = LengthDelimited(0, codex.u8, codex.buffer)
codex.buffer_u16 = LengthDelimited(0, codex.u16, codex.buffer)
codex.buffer_u32 = LengthDelimited(0, codex.u32, codex.buffer)
function FixedBuffer (bytes) {
var c = V.Buffer(bytes)
c.bytes = bytes
return c
}
//common fixed buffer sizes
codex.fixed_4 = FixedBuffer(4) //ipv4
codex.fixed_16 = FixedBuffer(16) //ipv6
codex.fixed_20 = FixedBuffer(20) //sha1
codex.fixed_32 = FixedBuffer(32) //sha256
codex.fixed_64 = FixedBuffer(64) //sha3, ed25519 signature
for(var k in codex)
codex[k].type = k
module.exports = codex