]>
Commit | Line | Data |
---|---|---|
107c1cdb ND |
1 | package msgpack |
2 | ||
3 | import ( | |
4 | "errors" | |
5 | "fmt" | |
6 | "reflect" | |
7 | ) | |
8 | ||
9 | var interfaceType = reflect.TypeOf((*interface{})(nil)).Elem() | |
10 | var stringType = reflect.TypeOf((*string)(nil)).Elem() | |
11 | ||
12 | var valueDecoders []decoderFunc | |
13 | ||
14 | func init() { | |
15 | valueDecoders = []decoderFunc{ | |
16 | reflect.Bool: decodeBoolValue, | |
17 | reflect.Int: decodeInt64Value, | |
18 | reflect.Int8: decodeInt64Value, | |
19 | reflect.Int16: decodeInt64Value, | |
20 | reflect.Int32: decodeInt64Value, | |
21 | reflect.Int64: decodeInt64Value, | |
22 | reflect.Uint: decodeUint64Value, | |
23 | reflect.Uint8: decodeUint64Value, | |
24 | reflect.Uint16: decodeUint64Value, | |
25 | reflect.Uint32: decodeUint64Value, | |
26 | reflect.Uint64: decodeUint64Value, | |
27 | reflect.Float32: decodeFloat32Value, | |
28 | reflect.Float64: decodeFloat64Value, | |
29 | reflect.Complex64: decodeUnsupportedValue, | |
30 | reflect.Complex128: decodeUnsupportedValue, | |
31 | reflect.Array: decodeArrayValue, | |
32 | reflect.Chan: decodeUnsupportedValue, | |
33 | reflect.Func: decodeUnsupportedValue, | |
34 | reflect.Interface: decodeInterfaceValue, | |
35 | reflect.Map: decodeMapValue, | |
36 | reflect.Ptr: decodeUnsupportedValue, | |
37 | reflect.Slice: decodeSliceValue, | |
38 | reflect.String: decodeStringValue, | |
39 | reflect.Struct: decodeStructValue, | |
40 | reflect.UnsafePointer: decodeUnsupportedValue, | |
41 | } | |
42 | } | |
43 | ||
44 | func mustSet(v reflect.Value) error { | |
45 | if !v.CanSet() { | |
46 | return fmt.Errorf("msgpack: Decode(nonsettable %s)", v.Type()) | |
47 | } | |
48 | return nil | |
49 | } | |
50 | ||
51 | func getDecoder(typ reflect.Type) decoderFunc { | |
52 | kind := typ.Kind() | |
53 | ||
54 | decoder, ok := typDecMap[typ] | |
55 | if ok { | |
56 | return decoder | |
57 | } | |
58 | ||
59 | if typ.Implements(customDecoderType) { | |
60 | return decodeCustomValue | |
61 | } | |
62 | if typ.Implements(unmarshalerType) { | |
63 | return unmarshalValue | |
64 | } | |
65 | ||
66 | // Addressable struct field value. | |
67 | if kind != reflect.Ptr { | |
68 | ptr := reflect.PtrTo(typ) | |
69 | if ptr.Implements(customDecoderType) { | |
70 | return decodeCustomValueAddr | |
71 | } | |
72 | if ptr.Implements(unmarshalerType) { | |
73 | return unmarshalValueAddr | |
74 | } | |
75 | } | |
76 | ||
77 | switch kind { | |
78 | case reflect.Ptr: | |
79 | return ptrDecoderFunc(typ) | |
80 | case reflect.Slice: | |
81 | elem := typ.Elem() | |
82 | switch elem.Kind() { | |
83 | case reflect.Uint8: | |
84 | return decodeBytesValue | |
85 | } | |
86 | switch elem { | |
87 | case stringType: | |
88 | return decodeStringSliceValue | |
89 | } | |
90 | case reflect.Array: | |
91 | if typ.Elem().Kind() == reflect.Uint8 { | |
92 | return decodeByteArrayValue | |
93 | } | |
94 | case reflect.Map: | |
95 | if typ.Key() == stringType { | |
96 | switch typ.Elem() { | |
97 | case stringType: | |
98 | return decodeMapStringStringValue | |
99 | case interfaceType: | |
100 | return decodeMapStringInterfaceValue | |
101 | } | |
102 | } | |
103 | } | |
104 | return valueDecoders[kind] | |
105 | } | |
106 | ||
107 | func ptrDecoderFunc(typ reflect.Type) decoderFunc { | |
108 | decoder := getDecoder(typ.Elem()) | |
109 | return func(d *Decoder, v reflect.Value) error { | |
110 | if d.hasNilCode() { | |
111 | if err := mustSet(v); err != nil { | |
112 | return err | |
113 | } | |
114 | if !v.IsNil() { | |
115 | v.Set(reflect.Zero(v.Type())) | |
116 | } | |
117 | return d.DecodeNil() | |
118 | } | |
119 | if v.IsNil() { | |
120 | if err := mustSet(v); err != nil { | |
121 | return err | |
122 | } | |
123 | v.Set(reflect.New(v.Type().Elem())) | |
124 | } | |
125 | return decoder(d, v.Elem()) | |
126 | } | |
127 | } | |
128 | ||
129 | func decodeCustomValueAddr(d *Decoder, v reflect.Value) error { | |
130 | if !v.CanAddr() { | |
131 | return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface()) | |
132 | } | |
133 | return decodeCustomValue(d, v.Addr()) | |
134 | } | |
135 | ||
136 | func decodeCustomValue(d *Decoder, v reflect.Value) error { | |
137 | if d.hasNilCode() { | |
138 | return d.decodeNilValue(v) | |
139 | } | |
140 | ||
141 | if v.IsNil() { | |
142 | v.Set(reflect.New(v.Type().Elem())) | |
143 | } | |
144 | ||
145 | decoder := v.Interface().(CustomDecoder) | |
146 | return decoder.DecodeMsgpack(d) | |
147 | } | |
148 | ||
149 | func unmarshalValueAddr(d *Decoder, v reflect.Value) error { | |
150 | if !v.CanAddr() { | |
151 | return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface()) | |
152 | } | |
153 | return unmarshalValue(d, v.Addr()) | |
154 | } | |
155 | ||
156 | func unmarshalValue(d *Decoder, v reflect.Value) error { | |
157 | if d.hasNilCode() { | |
158 | return d.decodeNilValue(v) | |
159 | } | |
160 | ||
161 | if v.IsNil() { | |
162 | v.Set(reflect.New(v.Type().Elem())) | |
163 | } | |
164 | ||
165 | if d.extLen != 0 { | |
166 | b, err := d.readN(d.extLen) | |
167 | if err != nil { | |
168 | return err | |
169 | } | |
170 | d.rec = b | |
171 | } else { | |
172 | d.rec = makeBuffer() | |
173 | if err := d.Skip(); err != nil { | |
174 | return err | |
175 | } | |
176 | } | |
177 | ||
178 | unmarshaler := v.Interface().(Unmarshaler) | |
179 | err := unmarshaler.UnmarshalMsgpack(d.rec) | |
180 | d.rec = nil | |
181 | return err | |
182 | } | |
183 | ||
184 | func decodeBoolValue(d *Decoder, v reflect.Value) error { | |
185 | flag, err := d.DecodeBool() | |
186 | if err != nil { | |
187 | return err | |
188 | } | |
189 | if err = mustSet(v); err != nil { | |
190 | return err | |
191 | } | |
192 | v.SetBool(flag) | |
193 | return nil | |
194 | } | |
195 | ||
196 | func decodeInterfaceValue(d *Decoder, v reflect.Value) error { | |
197 | if v.IsNil() { | |
198 | return d.interfaceValue(v) | |
199 | } | |
200 | ||
201 | elem := v.Elem() | |
202 | if !elem.CanAddr() { | |
203 | if d.hasNilCode() { | |
204 | v.Set(reflect.Zero(v.Type())) | |
205 | return d.DecodeNil() | |
206 | } | |
207 | } | |
208 | ||
209 | return d.DecodeValue(elem) | |
210 | } | |
211 | ||
212 | func (d *Decoder) interfaceValue(v reflect.Value) error { | |
213 | vv, err := d.decodeInterfaceCond() | |
214 | if err != nil { | |
215 | return err | |
216 | } | |
217 | ||
218 | if vv != nil { | |
219 | if v.Type() == errorType { | |
220 | if vv, ok := vv.(string); ok { | |
221 | v.Set(reflect.ValueOf(errors.New(vv))) | |
222 | return nil | |
223 | } | |
224 | } | |
225 | ||
226 | v.Set(reflect.ValueOf(vv)) | |
227 | } | |
228 | ||
229 | return nil | |
230 | } | |
231 | ||
232 | func decodeUnsupportedValue(d *Decoder, v reflect.Value) error { | |
233 | return fmt.Errorf("msgpack: Decode(unsupported %s)", v.Type()) | |
234 | } |