-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcollate_cbor.go
130 lines (117 loc) · 2.99 KB
/
collate_cbor.go
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
// transform binary-collated data into cbor encoding.
// cnf: NumberKind, ContainerEncoding, arrayLenPrefix, propertyLenPrefix
package gson
//---- collate to cbor
func collate2cbor(code, out []byte, config *Config) (int, int) {
if len(code) == 0 {
return 0, 0
}
var scratch [64]byte
m, n := 1, 0
switch code[0] {
case TypeMissing:
n += valtext2cbor(string(MissingLiteral), out[n:])
return m + 1, n
case TypeNull:
n += cborNull(out[n:])
return m + 1, n
case TypeTrue:
n += cborTrue(out[n:])
return m + 1, n
case TypeFalse:
n += cborFalse(out[n:])
return m + 1, n
case TypeNumber:
x := getDatum(code[m:])
// -1 is to skip terminator
ui, i, f, what := collated2Number(code[m:m+x-1], config.nk)
switch what {
case 1:
n += valuint642cbor(ui, out[n:])
case 2:
n += valint642cbor(i, out[n:])
case 3:
n += valfloat642cbor(f, out[n:])
}
return m + x, n
case TypeString:
var x int
bufn := config.bufferh.getbuffer(len(code[m:]) * 5)
scratch := bufn.data
scratch, x = collate2String(code[m:], scratch[:])
n += valtext2cbor(bytes2str(scratch), out[n:])
config.bufferh.putbuffer(bufn)
return m + x, n
case TypeBinary:
x := getDatum(code[m:])
n += valbytes2cbor(code[m:m+x-1], out[n:])
return m + x, n
case TypeArray:
if config.arrayLenPrefix {
if code[m] != TypeLength {
panic("collate decode expected array length prefix")
}
x := getDatum(code[m:])
// -1 skip terminator
collated2Int(code[m:m+x-1], scratch[:]) // skip length
m += x
}
nn, nnn := n, n
if config.ct == LengthPrefix {
nn, nnn = n+32, n+32
} else if config.ct == Stream {
nnn += arrayStart(out[nnn:])
}
ln := 0
for code[m] != Terminator {
x, y := collate2cbor(code[m:], out[nnn:], config)
m, nnn = m+x, nnn+y
ln++
}
if config.ct == LengthPrefix {
x := valuint642cbor(uint64(ln), out[n:])
out[n] = (out[n] & 0x1f) | cborType4 // fix type from type0->type4
n += x
n += copy(out[n:], out[nn:nnn])
} else if config.ct == Stream {
nnn += breakStop(out[nnn:])
n = nnn
}
return m + 1, n
case TypeObj:
if config.propertyLenPrefix {
if code[m] != TypeLength {
panic("collate decode expected property length prefix")
}
x := getDatum(code[m:])
// -1 skip terminator
collated2Int(code[m:m+x-1], scratch[:]) // skip length
m += x
}
nn, nnn := n, n
if config.ct == LengthPrefix {
nn, nnn = n+32, n+32
} else if config.ct == Stream {
nnn += mapStart(out[nnn:])
}
ln := 0
for code[m] != Terminator {
x, y := collate2cbor(code[m:], out[nnn:], config)
m, nnn = m+x, nnn+y
x, y = collate2cbor(code[m:], out[nnn:], config)
m, nnn = m+x, nnn+y
ln++
}
if config.ct == LengthPrefix {
x := valuint642cbor(uint64(ln), out[n:])
out[n] = (out[n] & 0x1f) | cborType5 // fix type from type0->type5
n += x
n += copy(out[n:], out[nn:nnn])
} else if config.ct == Stream {
nnn += breakStop(out[nnn:])
n = nnn
}
return m + 1, n
}
panic("collate decode to cbor invalid binary")
}