mapslice.go

  1// Copyright (c) Microsoft Corporation.
  2// Licensed under the MIT license.
  3
  4package json
  5
  6import (
  7	"encoding/json"
  8	"fmt"
  9	"reflect"
 10)
 11
 12// unmarshalMap unmarshal's a map.
 13func unmarshalMap(dec *json.Decoder, m reflect.Value) error {
 14	if m.Kind() != reflect.Ptr || m.Elem().Kind() != reflect.Map {
 15		panic("unmarshalMap called on non-*map value")
 16	}
 17	mapValueType := m.Elem().Type().Elem()
 18	walk := mapWalk{dec: dec, m: m, valueType: mapValueType}
 19	if err := walk.run(); err != nil {
 20		return err
 21	}
 22	return nil
 23}
 24
 25type mapWalk struct {
 26	dec       *json.Decoder
 27	key       string
 28	m         reflect.Value
 29	valueType reflect.Type
 30}
 31
 32// run runs our decoder state machine.
 33func (m *mapWalk) run() error {
 34	var state = m.start
 35	var err error
 36	for {
 37		state, err = state()
 38		if err != nil {
 39			return err
 40		}
 41		if state == nil {
 42			return nil
 43		}
 44	}
 45}
 46
 47func (m *mapWalk) start() (stateFn, error) {
 48	// maps can have custom unmarshaler's.
 49	if hasUnmarshalJSON(m.m) {
 50		err := m.dec.Decode(m.m.Interface())
 51		if err != nil {
 52			return nil, err
 53		}
 54		return nil, nil
 55	}
 56
 57	// We only want to use this if the map value is:
 58	// *struct/struct/map/slice
 59	// otherwise use standard decode
 60	t, _ := m.valueBaseType()
 61	switch t.Kind() {
 62	case reflect.Struct, reflect.Map, reflect.Slice:
 63		delim, err := m.dec.Token()
 64		if err != nil {
 65			return nil, err
 66		}
 67		// This indicates the value was set to JSON null.
 68		if delim == nil {
 69			return nil, nil
 70		}
 71		if !delimIs(delim, '{') {
 72			return nil, fmt.Errorf("Unmarshal expected opening {, received %v", delim)
 73		}
 74		return m.next, nil
 75	case reflect.Ptr:
 76		return nil, fmt.Errorf("do not support maps with values of '**type' or '*reference")
 77	}
 78
 79	// This is a basic map type, so just use Decode().
 80	if err := m.dec.Decode(m.m.Interface()); err != nil {
 81		return nil, err
 82	}
 83
 84	return nil, nil
 85}
 86
 87func (m *mapWalk) next() (stateFn, error) {
 88	if m.dec.More() {
 89		key, err := m.dec.Token()
 90		if err != nil {
 91			return nil, err
 92		}
 93		m.key = key.(string)
 94		return m.storeValue, nil
 95	}
 96	// No more entries, so remove final }.
 97	_, err := m.dec.Token()
 98	if err != nil {
 99		return nil, err
100	}
101	return nil, nil
102}
103
104func (m *mapWalk) storeValue() (stateFn, error) {
105	v := m.valueType
106	for {
107		switch v.Kind() {
108		case reflect.Ptr:
109			v = v.Elem()
110			continue
111		case reflect.Struct:
112			return m.storeStruct, nil
113		case reflect.Map:
114			return m.storeMap, nil
115		case reflect.Slice:
116			return m.storeSlice, nil
117		}
118		return nil, fmt.Errorf("bug: mapWalk.storeValue() called on unsupported type: %v", v.Kind())
119	}
120}
121
122func (m *mapWalk) storeStruct() (stateFn, error) {
123	v := newValue(m.valueType)
124	if err := unmarshalStruct(m.dec, v.Interface()); err != nil {
125		return nil, err
126	}
127
128	if m.valueType.Kind() == reflect.Ptr {
129		m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v)
130		return m.next, nil
131	}
132	m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v.Elem())
133
134	return m.next, nil
135}
136
137func (m *mapWalk) storeMap() (stateFn, error) {
138	v := reflect.MakeMap(m.valueType)
139	ptr := newValue(v.Type())
140	ptr.Elem().Set(v)
141	if err := unmarshalMap(m.dec, ptr); err != nil {
142		return nil, err
143	}
144
145	m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v)
146
147	return m.next, nil
148}
149
150func (m *mapWalk) storeSlice() (stateFn, error) {
151	v := newValue(m.valueType)
152	if err := unmarshalSlice(m.dec, v); err != nil {
153		return nil, err
154	}
155
156	m.m.Elem().SetMapIndex(reflect.ValueOf(m.key), v.Elem())
157
158	return m.next, nil
159}
160
161// valueType returns the underlying Type. So a *struct would yield
162// struct, etc...
163func (m *mapWalk) valueBaseType() (reflect.Type, bool) {
164	ptr := false
165	v := m.valueType
166	if v.Kind() == reflect.Ptr {
167		ptr = true
168		v = v.Elem()
169	}
170	return v, ptr
171}
172
173// unmarshalSlice unmarshal's the next value, which must be a slice, into
174// ptrSlice, which must be a pointer to a slice. newValue() can be use to
175// create the slice.
176func unmarshalSlice(dec *json.Decoder, ptrSlice reflect.Value) error {
177	if ptrSlice.Kind() != reflect.Ptr || ptrSlice.Elem().Kind() != reflect.Slice {
178		panic("unmarshalSlice called on non-*[]slice value")
179	}
180	sliceValueType := ptrSlice.Elem().Type().Elem()
181	walk := sliceWalk{
182		dec:       dec,
183		s:         ptrSlice,
184		valueType: sliceValueType,
185	}
186	if err := walk.run(); err != nil {
187		return err
188	}
189
190	return nil
191}
192
193type sliceWalk struct {
194	dec       *json.Decoder
195	s         reflect.Value // *[]slice
196	valueType reflect.Type
197}
198
199// run runs our decoder state machine.
200func (s *sliceWalk) run() error {
201	var state = s.start
202	var err error
203	for {
204		state, err = state()
205		if err != nil {
206			return err
207		}
208		if state == nil {
209			return nil
210		}
211	}
212}
213
214func (s *sliceWalk) start() (stateFn, error) {
215	// slices can have custom unmarshaler's.
216	if hasUnmarshalJSON(s.s) {
217		err := s.dec.Decode(s.s.Interface())
218		if err != nil {
219			return nil, err
220		}
221		return nil, nil
222	}
223
224	// We only want to use this if the slice value is:
225	// []*struct/[]struct/[]map/[]slice
226	// otherwise use standard decode
227	t := s.valueBaseType()
228
229	switch t.Kind() {
230	case reflect.Ptr:
231		return nil, fmt.Errorf("cannot unmarshal into a **<type> or *<reference>")
232	case reflect.Struct, reflect.Map, reflect.Slice:
233		delim, err := s.dec.Token()
234		if err != nil {
235			return nil, err
236		}
237		// This indicates the value was set to nil.
238		if delim == nil {
239			return nil, nil
240		}
241		if !delimIs(delim, '[') {
242			return nil, fmt.Errorf("Unmarshal expected opening [, received %v", delim)
243		}
244		return s.next, nil
245	}
246
247	if err := s.dec.Decode(s.s.Interface()); err != nil {
248		return nil, err
249	}
250	return nil, nil
251}
252
253func (s *sliceWalk) next() (stateFn, error) {
254	if s.dec.More() {
255		return s.storeValue, nil
256	}
257	// Nothing left in the slice, remove closing ]
258	_, err := s.dec.Token()
259	return nil, err
260}
261
262func (s *sliceWalk) storeValue() (stateFn, error) {
263	t := s.valueBaseType()
264	switch t.Kind() {
265	case reflect.Ptr:
266		return nil, fmt.Errorf("do not support 'pointer to pointer' or 'pointer to reference' types")
267	case reflect.Struct:
268		return s.storeStruct, nil
269	case reflect.Map:
270		return s.storeMap, nil
271	case reflect.Slice:
272		return s.storeSlice, nil
273	}
274	return nil, fmt.Errorf("bug: sliceWalk.storeValue() called on unsupported type: %v", t.Kind())
275}
276
277func (s *sliceWalk) storeStruct() (stateFn, error) {
278	v := newValue(s.valueType)
279	if err := unmarshalStruct(s.dec, v.Interface()); err != nil {
280		return nil, err
281	}
282
283	if s.valueType.Kind() == reflect.Ptr {
284		s.s.Elem().Set(reflect.Append(s.s.Elem(), v))
285		return s.next, nil
286	}
287
288	s.s.Elem().Set(reflect.Append(s.s.Elem(), v.Elem()))
289	return s.next, nil
290}
291
292func (s *sliceWalk) storeMap() (stateFn, error) {
293	v := reflect.MakeMap(s.valueType)
294	ptr := newValue(v.Type())
295	ptr.Elem().Set(v)
296
297	if err := unmarshalMap(s.dec, ptr); err != nil {
298		return nil, err
299	}
300
301	s.s.Elem().Set(reflect.Append(s.s.Elem(), v))
302
303	return s.next, nil
304}
305
306func (s *sliceWalk) storeSlice() (stateFn, error) {
307	v := newValue(s.valueType)
308	if err := unmarshalSlice(s.dec, v); err != nil {
309		return nil, err
310	}
311
312	s.s.Elem().Set(reflect.Append(s.s.Elem(), v.Elem()))
313
314	return s.next, nil
315}
316
317// valueType returns the underlying Type. So a *struct would yield
318// struct, etc...
319func (s *sliceWalk) valueBaseType() reflect.Type {
320	v := s.valueType
321	if v.Kind() == reflect.Ptr {
322		v = v.Elem()
323	}
324	return v
325}
326
327// newValue() returns a new *type that represents type passed.
328func newValue(valueType reflect.Type) reflect.Value {
329	if valueType.Kind() == reflect.Ptr {
330		return reflect.New(valueType.Elem())
331	}
332	return reflect.New(valueType)
333}