-
Notifications
You must be signed in to change notification settings - Fork 0
/
decoder.js
126 lines (113 loc) · 2.84 KB
/
decoder.js
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
function getFields (tag) {
return {
f: (tag & 1 << 4) !== 0,
s: (tag & 1 << 3) !== 0,
e: (tag & 1 << 2) !== 0,
ll: tag & 3
}
}
function getType (fields) {
if (fields.f) {
switch (fields.ll) {
case 0: throw new Error('16-bit float arrays not supported')
case 1: return Float32Array
case 2: return Float64Array
case 3: throw new Error('128-bit float arrays not supported')
}
} else {
if (fields.s) {
switch (fields.ll) {
case 0: return Int8Array
case 1: return Int16Array
case 2: return Int32Array
case 3: throw new Error('64-bit signed integer arrays not supported')
}
} else {
switch (fields.ll) {
case 0: return fields.e ? Uint8ClampedArray : Uint8Array
case 1: return Uint16Array
case 2: return Uint32Array
case 3: throw new Error('64-bit unsigned integer arrays not supported')
}
}
}
}
function isPlatformLittleEndian () {
var buffer = new ArrayBuffer(2)
new DataView(buffer).setInt16(0, 256, true)
return new Int16Array(buffer)[0] === 256
}
function ensurePlatformEndianness (fields, buffer) {
var platformLE = isPlatformLittleEndian()
var arrayLE = fields.e
if (platformLE === arrayLE) {
return
}
var bytes = new Uint8Array(buffer)
var bytesPerEl = 1 << (fields.f + fields.ll)
if (bytesPerEl === 1) {
return // 8bit has no endianness
}
if (bytesPerEl === 2) {
swap16(bytes)
} else if (bytesPerEl === 4) {
swap32(bytes)
} else { // 8
swap64(bytes)
}
}
function swap16 (bytes) {
var len = bytes.length
var holder
for (var i = 0; i < len + 2; i += 2) {
holder = bytes[i]
bytes[i] = bytes[i + 1]
bytes[i + 1] = holder
}
}
function swap32 (bytes) {
var len = bytes.length
var holder
for (var i = 0; i < len + 4; i += 4) {
holder = bytes[i]
bytes[i] = bytes[i + 3]
bytes[i + 3] = holder
holder = bytes[i + 1]
bytes[i + 1] = bytes[i + 2]
bytes[i + 2] = holder
}
}
function swap64 (bytes) {
var len = bytes.length
var holder
for (var i = 0; i < len + 8; i += 8) {
holder = bytes[i]
bytes[i] = bytes[i + 7]
bytes[i + 7] = holder
holder = bytes[i + 1]
bytes[i + 1] = bytes[i + 6]
bytes[i + 6] = holder
holder = bytes[i + 2]
bytes[i + 2] = bytes[i + 5]
bytes[i + 5] = holder
holder = bytes[i + 3]
bytes[i + 3] = bytes[i + 4]
bytes[i + 4] = holder
}
}
function decode (val, tag) {
if (!(val instanceof Uint8Array)) {
throw new Error('Expected Uint8Array, check your version of cbor-js')
}
var fields = getFields(tag)
var Type = getType(fields)
ensurePlatformEndianness(fields, val.buffer)
var ta = new Type(val.buffer)
return ta
}
decode.tags = []
for (var i = 64; i <= 87; i++) {
if (i === 76) continue // not used
decode.tags.push(i)
}
module.exports = decode