forked from rvagg/cborg
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjump.js
More file actions
207 lines (200 loc) · 7.69 KB
/
Copy pathjump.js
File metadata and controls
207 lines (200 loc) · 7.69 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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import { Token, Type } from './token.js'
import * as uint from './0uint.js'
import * as negint from './1negint.js'
import * as bytes from './2bytes.js'
import * as string from './3string.js'
import * as array from './4array.js'
import * as map from './5map.js'
import * as tag from './6tag.js'
import * as float from './7float.js'
import { decodeErrPrefix } from './common.js'
import { fromArray } from './byte-utils.js'
/**
* @typedef {import('../interface.js').DecodeOptions} DecodeOptions
*/
/**
* @param {Uint8Array} data
* @param {number} pos
* @param {number} minor
*/
function invalidMinor (data, pos, minor) {
throw new Error(`${decodeErrPrefix} encountered invalid minor (${minor}) for major ${data[pos] >>> 5}`)
}
/**
* @param {string} msg
* @returns {()=>any}
*/
function errorer (msg) {
return () => { throw new Error(`${decodeErrPrefix} ${msg}`) }
}
/** @type {((data:Uint8Array, pos:number, minor:number, options?:DecodeOptions) => any)[]} */
export const jump = []
// unsigned integer, 0x00..0x17 (0..23)
for (let i = 0; i <= 0x17; i++) {
jump[i] = invalidMinor // uint.decodeUintCompact, handled by quick[]
}
jump[0x18] = uint.decodeUint8 // unsigned integer, one-byte uint8_t follows
jump[0x19] = uint.decodeUint16 // unsigned integer, two-byte uint16_t follows
jump[0x1a] = uint.decodeUint32 // unsigned integer, four-byte uint32_t follows
jump[0x1b] = uint.decodeUint64 // unsigned integer, eight-byte uint64_t follows
jump[0x1c] = invalidMinor
jump[0x1d] = invalidMinor
jump[0x1e] = invalidMinor
jump[0x1f] = invalidMinor
// negative integer, -1-0x00..-1-0x17 (-1..-24)
for (let i = 0x20; i <= 0x37; i++) {
jump[i] = invalidMinor // negintDecode, handled by quick[]
}
jump[0x38] = negint.decodeNegint8 // negative integer, -1-n one-byte uint8_t for n follows
jump[0x39] = negint.decodeNegint16 // negative integer, -1-n two-byte uint16_t for n follows
jump[0x3a] = negint.decodeNegint32 // negative integer, -1-n four-byte uint32_t for follows
jump[0x3b] = negint.decodeNegint64 // negative integer, -1-n eight-byte uint64_t for follows
jump[0x3c] = invalidMinor
jump[0x3d] = invalidMinor
jump[0x3e] = invalidMinor
jump[0x3f] = invalidMinor
// byte string, 0x00..0x17 bytes follow
for (let i = 0x40; i <= 0x57; i++) {
jump[i] = bytes.decodeBytesCompact
}
jump[0x58] = bytes.decodeBytes8 // byte string, one-byte uint8_t for n, and then n bytes follow
jump[0x59] = bytes.decodeBytes16 // byte string, two-byte uint16_t for n, and then n bytes follow
jump[0x5a] = bytes.decodeBytes32 // byte string, four-byte uint32_t for n, and then n bytes follow
jump[0x5b] = bytes.decodeBytes64 // byte string, eight-byte uint64_t for n, and then n bytes follow
jump[0x5c] = invalidMinor
jump[0x5d] = invalidMinor
jump[0x5e] = invalidMinor
jump[0x5f] = errorer('indefinite length bytes/strings are not supported') // byte string, byte strings follow, terminated by "break"
// UTF-8 string 0x00..0x17 bytes follow
for (let i = 0x60; i <= 0x77; i++) {
jump[i] = string.decodeStringCompact
}
jump[0x78] = string.decodeString8 // UTF-8 string, one-byte uint8_t for n, and then n bytes follow
jump[0x79] = string.decodeString16 // UTF-8 string, two-byte uint16_t for n, and then n bytes follow
jump[0x7a] = string.decodeString32 // UTF-8 string, four-byte uint32_t for n, and then n bytes follow
jump[0x7b] = string.decodeString64 // UTF-8 string, eight-byte uint64_t for n, and then n bytes follow
jump[0x7c] = invalidMinor
jump[0x7d] = invalidMinor
jump[0x7e] = invalidMinor
jump[0x7f] = errorer('indefinite length bytes/strings are not supported') // UTF-8 strings follow, terminated by "break"
// array, 0x00..0x17 data items follow
for (let i = 0x80; i <= 0x97; i++) {
jump[i] = array.decodeArrayCompact
}
jump[0x98] = array.decodeArray8 // array, one-byte uint8_t for n, and then n data items follow
jump[0x99] = array.decodeArray16 // array, two-byte uint16_t for n, and then n data items follow
jump[0x9a] = array.decodeArray32 // array, four-byte uint32_t for n, and then n data items follow
jump[0x9b] = array.decodeArray64 // array, eight-byte uint64_t for n, and then n data items follow
jump[0x9c] = invalidMinor
jump[0x9d] = invalidMinor
jump[0x9e] = invalidMinor
jump[0x9f] = array.decodeArrayIndefinite // array, data items follow, terminated by "break"
// map, 0x00..0x17 pairs of data items follow
for (let i = 0xa0; i <= 0xb7; i++) {
jump[i] = map.decodeMapCompact
}
jump[0xb8] = map.decodeMap8 // map, one-byte uint8_t for n, and then n pairs of data items follow
jump[0xb9] = map.decodeMap16 // map, two-byte uint16_t for n, and then n pairs of data items follow
jump[0xba] = map.decodeMap32 // map, four-byte uint32_t for n, and then n pairs of data items follow
jump[0xbb] = map.decodeMap64 // map, eight-byte uint64_t for n, and then n pairs of data items follow
jump[0xbc] = invalidMinor
jump[0xbd] = invalidMinor
jump[0xbe] = invalidMinor
jump[0xbf] = map.decodeMapIndefinite // map, pairs of data items follow, terminated by "break"
// tags
for (let i = 0xc0; i <= 0xd7; i++) {
jump[i] = tag.decodeTagCompact
}
jump[0xd8] = tag.decodeTag8
jump[0xd9] = tag.decodeTag16
jump[0xda] = tag.decodeTag32
jump[0xdb] = tag.decodeTag64
jump[0xdc] = invalidMinor
jump[0xdd] = invalidMinor
jump[0xde] = invalidMinor
jump[0xdf] = invalidMinor
// 0xe0..0xf3 simple values, unsupported
for (let i = 0xe0; i <= 0xf3; i++) {
jump[i] = errorer('simple values are not supported')
}
jump[0xf4] = invalidMinor // false, handled by quick[]
jump[0xf5] = invalidMinor // true, handled by quick[]
jump[0xf6] = invalidMinor // null, handled by quick[]
jump[0xf7] = float.decodeUndefined // undefined
jump[0xf8] = errorer('simple values are not supported') // simple value, one byte follows, unsupported
jump[0xf9] = float.decodeFloat16 // half-precision float (two-byte IEEE 754)
jump[0xfa] = float.decodeFloat32 // single-precision float (four-byte IEEE 754)
jump[0xfb] = float.decodeFloat64 // double-precision float (eight-byte IEEE 754)
jump[0xfc] = invalidMinor
jump[0xfd] = invalidMinor
jump[0xfe] = invalidMinor
jump[0xff] = float.decodeBreak // "break" stop code
/** @type {Token[]} */
export const quick = []
// ints <24
for (let i = 0; i < 24; i++) {
quick[i] = new Token(Type.uint, i, 1)
}
// negints >= -24
for (let i = -1; i >= -24; i--) {
quick[31 - i] = new Token(Type.negint, i, 1)
}
// empty bytes
quick[0x40] = new Token(Type.bytes, new Uint8Array(0), 1)
// empty string
quick[0x60] = new Token(Type.string, '', 1)
// empty list
quick[0x80] = new Token(Type.array, 0, 1)
// empty map
quick[0xa0] = new Token(Type.map, 0, 1)
// false
quick[0xf4] = new Token(Type.false, false, 1)
// true
quick[0xf5] = new Token(Type.true, true, 1)
// null
quick[0xf6] = new Token(Type.null, null, 1)
/**
* @param {Token} token
* @returns {Uint8Array<ArrayBuffer>|undefined}
*/
export function quickEncodeToken (token) {
switch (token.type) {
case Type.false:
return fromArray([0xf4])
case Type.true:
return fromArray([0xf5])
case Type.null:
return fromArray([0xf6])
case Type.bytes:
if (!token.value.length) {
return fromArray([0x40])
}
return
case Type.string:
if (token.value === '') {
return fromArray([0x60])
}
return
case Type.array:
if (token.value === 0) {
return fromArray([0x80])
}
// shouldn't be possible if this were called when there was only one token
return
case Type.map:
if (token.value === 0) {
return fromArray([0xa0])
}
// shouldn't be possible if this were called when there was only one token
return
case Type.uint:
if (token.value < 24) {
return fromArray([Number(token.value)])
}
return
case Type.negint:
if (token.value >= -24) {
return fromArray([31 - Number(token.value)])
}
}
}