Skip to content

Commit 3e02be0

Browse files
committed
binary: Add variant data reader/writer
1 parent 89c9d91 commit 3e02be0

File tree

1 file changed

+305
-0
lines changed

1 file changed

+305
-0
lines changed

common/binary/variant_data.go

+305
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
package binary
2+
3+
import (
4+
"bufio"
5+
"errors"
6+
"io"
7+
"reflect"
8+
9+
E "github.com/sagernet/sing/common/exceptions"
10+
)
11+
12+
func ReadDataSlice(r *bufio.Reader, order ByteOrder, data ...any) error {
13+
for index, item := range data {
14+
err := ReadData(r, order, item)
15+
if err != nil {
16+
return E.Cause(err, "[", index, "]")
17+
}
18+
}
19+
return nil
20+
}
21+
22+
func ReadData(r *bufio.Reader, order ByteOrder, data any) error {
23+
switch dataPtr := data.(type) {
24+
case *[]uint8:
25+
bytesLen, err := ReadUvarint(r)
26+
if err != nil {
27+
return E.Cause(err, "bytes length")
28+
}
29+
newBytes := make([]uint8, bytesLen)
30+
_, err = io.ReadFull(r, newBytes)
31+
if err != nil {
32+
return E.Cause(err, "bytes value")
33+
}
34+
*dataPtr = newBytes
35+
default:
36+
if intBaseDataSize(data) != 0 {
37+
return Read(r, order, data)
38+
}
39+
}
40+
dataValue := reflect.ValueOf(data)
41+
if dataValue.Kind() == reflect.Pointer {
42+
dataValue = dataValue.Elem()
43+
}
44+
return readData(r, order, dataValue)
45+
}
46+
47+
func readData(r *bufio.Reader, order ByteOrder, data reflect.Value) error {
48+
switch data.Kind() {
49+
case reflect.Pointer:
50+
pointerValue, err := r.ReadByte()
51+
if err != nil {
52+
return err
53+
}
54+
if pointerValue == 0 {
55+
data.SetZero()
56+
return nil
57+
}
58+
if data.IsNil() {
59+
data.Set(reflect.New(data.Type().Elem()))
60+
}
61+
return readData(r, order, data.Elem())
62+
case reflect.String:
63+
stringLength, err := ReadUvarint(r)
64+
if err != nil {
65+
return E.Cause(err, "string length")
66+
}
67+
if stringLength == 0 {
68+
data.SetZero()
69+
} else {
70+
stringData := make([]byte, stringLength)
71+
_, err = io.ReadFull(r, stringData)
72+
if err != nil {
73+
return E.Cause(err, "string value")
74+
}
75+
data.SetString(string(stringData))
76+
}
77+
case reflect.Array:
78+
arrayLen := data.Len()
79+
for i := 0; i < arrayLen; i++ {
80+
err := readData(r, order, data.Index(i))
81+
if err != nil {
82+
return E.Cause(err, "[", i, "]")
83+
}
84+
}
85+
case reflect.Slice:
86+
sliceLength, err := ReadUvarint(r)
87+
if err != nil {
88+
return E.Cause(err, "slice length")
89+
}
90+
if !data.IsNil() && data.Cap() >= int(sliceLength) {
91+
data.SetLen(int(sliceLength))
92+
} else if sliceLength > 0 {
93+
data.Set(reflect.MakeSlice(data.Type(), int(sliceLength), int(sliceLength)))
94+
}
95+
if sliceLength > 0 {
96+
if data.Type().Elem().Kind() == reflect.Uint8 {
97+
_, err = io.ReadFull(r, data.Bytes())
98+
if err != nil {
99+
return E.Cause(err, "bytes value")
100+
}
101+
} else {
102+
for index := 0; index < int(sliceLength); index++ {
103+
err = readData(r, order, data.Index(index))
104+
if err != nil {
105+
return E.Cause(err, "[", index, "]")
106+
}
107+
}
108+
}
109+
}
110+
case reflect.Map:
111+
mapLength, err := ReadUvarint(r)
112+
if err != nil {
113+
return E.Cause(err, "map length")
114+
}
115+
data.Set(reflect.MakeMap(data.Type()))
116+
for index := 0; index < int(mapLength); index++ {
117+
key := reflect.New(data.Type().Key()).Elem()
118+
err = readData(r, order, key)
119+
if err != nil {
120+
return E.Cause(err, "[", index, "].key")
121+
}
122+
value := reflect.New(data.Type().Elem()).Elem()
123+
err = readData(r, order, value)
124+
if err != nil {
125+
return E.Cause(err, "[", index, "].value")
126+
}
127+
data.SetMapIndex(key, value)
128+
}
129+
case reflect.Struct:
130+
fieldType := data.Type()
131+
fieldLen := data.NumField()
132+
for i := 0; i < fieldLen; i++ {
133+
field := data.Field(i)
134+
fieldName := fieldType.Field(i).Name
135+
if field.CanSet() || fieldName != "_" {
136+
err := readData(r, order, field)
137+
if err != nil {
138+
return E.Cause(err, fieldName)
139+
}
140+
}
141+
}
142+
default:
143+
size := dataSize(data)
144+
if size < 0 {
145+
return errors.New("invalid type " + reflect.TypeOf(data).String())
146+
}
147+
d := &decoder{order: order, buf: make([]byte, size)}
148+
_, err := io.ReadFull(r, d.buf)
149+
if err != nil {
150+
return err
151+
}
152+
d.value(data)
153+
}
154+
return nil
155+
}
156+
157+
func WriteDataSlice(writer *bufio.Writer, order ByteOrder, data ...any) error {
158+
for index, item := range data {
159+
err := WriteData(writer, order, item)
160+
if err != nil {
161+
return E.Cause(err, "[", index, "]")
162+
}
163+
}
164+
return nil
165+
}
166+
167+
func WriteData(writer *bufio.Writer, order ByteOrder, data any) error {
168+
switch dataPtr := data.(type) {
169+
case []uint8:
170+
_, err := writer.Write(AppendUvarint(writer.AvailableBuffer(), uint64(len(dataPtr))))
171+
if err != nil {
172+
return E.Cause(err, "bytes length")
173+
}
174+
_, err = writer.Write(dataPtr)
175+
if err != nil {
176+
return E.Cause(err, "bytes value")
177+
}
178+
default:
179+
if intBaseDataSize(data) != 0 {
180+
return Write(writer, order, data)
181+
}
182+
}
183+
return writeData(writer, order, reflect.Indirect(reflect.ValueOf(data)))
184+
}
185+
186+
func writeData(writer *bufio.Writer, order ByteOrder, data reflect.Value) error {
187+
switch data.Kind() {
188+
case reflect.Pointer:
189+
if data.IsNil() {
190+
err := writer.WriteByte(0)
191+
if err != nil {
192+
return err
193+
}
194+
} else {
195+
err := writer.WriteByte(1)
196+
if err != nil {
197+
return err
198+
}
199+
return writeData(writer, order, data.Elem())
200+
}
201+
case reflect.String:
202+
stringValue := data.String()
203+
_, err := writer.Write(AppendUvarint(writer.AvailableBuffer(), uint64(len(stringValue))))
204+
if err != nil {
205+
return E.Cause(err, "string length")
206+
}
207+
if stringValue != "" {
208+
_, err = writer.WriteString(stringValue)
209+
if err != nil {
210+
return E.Cause(err, "string value")
211+
}
212+
}
213+
case reflect.Array:
214+
dataLen := data.Len()
215+
for i := 0; i < dataLen; i++ {
216+
err := writeData(writer, order, data.Index(i))
217+
if err != nil {
218+
return E.Cause(err, "[", i, "]")
219+
}
220+
}
221+
case reflect.Slice:
222+
dataLen := data.Len()
223+
_, err := writer.Write(AppendUvarint(writer.AvailableBuffer(), uint64(dataLen)))
224+
if err != nil {
225+
return E.Cause(err, "slice length")
226+
}
227+
if dataLen > 0 {
228+
if data.Type().Elem().Kind() == reflect.Uint8 {
229+
_, err = writer.Write(data.Bytes())
230+
if err != nil {
231+
return E.Cause(err, "bytes value")
232+
}
233+
} else {
234+
for i := 0; i < dataLen; i++ {
235+
err = writeData(writer, order, data.Index(i))
236+
if err != nil {
237+
return E.Cause(err, "[", i, "]")
238+
}
239+
}
240+
}
241+
}
242+
case reflect.Map:
243+
dataLen := data.Len()
244+
_, err := writer.Write(AppendUvarint(writer.AvailableBuffer(), uint64(dataLen)))
245+
if err != nil {
246+
return E.Cause(err, "map length")
247+
}
248+
if dataLen > 0 {
249+
for index, key := range data.MapKeys() {
250+
err = writeData(writer, order, key)
251+
if err != nil {
252+
return E.Cause(err, "[", index, "].key")
253+
}
254+
err = writeData(writer, order, data.MapIndex(key))
255+
if err != nil {
256+
return E.Cause(err, "[", index, "].value")
257+
}
258+
}
259+
}
260+
case reflect.Struct:
261+
fieldType := data.Type()
262+
fieldLen := data.NumField()
263+
for i := 0; i < fieldLen; i++ {
264+
field := data.Field(i)
265+
fieldName := fieldType.Field(i).Name
266+
if field.CanSet() || fieldName != "_" {
267+
err := writeData(writer, order, field)
268+
if err != nil {
269+
return E.Cause(err, fieldName)
270+
}
271+
}
272+
}
273+
default:
274+
size := dataSize(data)
275+
if size < 0 {
276+
return errors.New("binary.Write: some values are not fixed-sized in type " + data.Type().String())
277+
}
278+
buf := make([]byte, size)
279+
e := &encoder{order: order, buf: buf}
280+
e.value(data)
281+
_, err := writer.Write(buf)
282+
if err != nil {
283+
return E.Cause(err, reflect.TypeOf(data).String())
284+
}
285+
}
286+
return nil
287+
}
288+
289+
func intBaseDataSize(data any) int {
290+
switch data.(type) {
291+
case bool, int8, uint8:
292+
return 1
293+
case int16, uint16:
294+
return 2
295+
case int32, uint32:
296+
return 4
297+
case int64, uint64:
298+
return 8
299+
case float32:
300+
return 4
301+
case float64:
302+
return 8
303+
}
304+
return 0
305+
}

0 commit comments

Comments
 (0)