forked from hprose/hprose-golang
/
array_decoder.go
104 lines (96 loc) · 2.71 KB
/
array_decoder.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
/**********************************************************\
| |
| hprose |
| |
| Official WebSite: http://www.hprose.com/ |
| http://www.hprose.org/ |
| |
\**********************************************************/
/**********************************************************\
* *
* io/array_decoder.go *
* *
* hprose array decoder for Go. *
* *
* LastModified: Oct 25, 2016 *
* Author: Ma Bingyao <andot@hprose.com> *
* *
\**********************************************************/
package io
import (
"errors"
"reflect"
"unsafe"
"github.com/hprose/hprose-golang/util"
)
func readBytesAsArray(r *Reader, v reflect.Value) {
if !r.Simple {
setReaderRef(r, v)
}
if v.Type().Elem().Kind() != reflect.Uint8 {
panic(errors.New("cannot be converted []byte to " + v.Type().String()))
}
n := v.Len()
sliceHeader := reflect.SliceHeader{
Data: (*emptyInterface)(unsafe.Pointer(&v)).ptr,
Len: n,
Cap: n,
}
b := *(*[]byte)(unsafe.Pointer(&sliceHeader))
l := r.readLength()
min := util.Min(n, l)
if _, err := r.Read(b[:min]); err != nil {
panic(err)
}
if l > min {
r.Next(l - min)
}
r.readByte()
}
func readListAsArray(r *Reader, v reflect.Value) {
n := v.Len()
l := r.ReadCount()
if !r.Simple {
setReaderRef(r, v)
}
min := util.Min(n, l)
for i := 0; i < min; i++ {
r.ReadValue(v.Index(i))
}
if min < l {
x := reflect.New(v.Type().Elem()).Elem()
for i := min; i < l; i++ {
r.ReadValue(x)
}
}
r.readByte()
}
func readRefAsArray(r *Reader, v reflect.Value) {
ref := r.readRef()
if b, ok := ref.([]byte); ok {
reflect.Copy(v, reflect.ValueOf(b))
return
}
if a, ok := ref.(reflect.Value); ok {
reflect.Copy(v, a)
return
}
panic(errors.New("value of type " +
reflect.TypeOf(ref).String() +
" cannot be converted to type array"))
}
var arrayDecoders = [256]func(r *Reader, v reflect.Value){
TagNull: nilDecoder,
TagEmpty: nilDecoder,
TagBytes: readBytesAsArray,
TagList: readListAsArray,
TagRef: readRefAsArray,
}
func arrayDecoder(r *Reader, v reflect.Value, tag byte) {
decoder := arrayDecoders[tag]
if decoder != nil {
decoder(r, v)
return
}
castError(tag, v.Type().String())
}