1package msgpack
2
3import (
4	"math"
5	"reflect"
6	"sort"
7
8	"github.com/vmihailenco/msgpack/v5/msgpcode"
9)
10
11func encodeMapValue(e *Encoder, v reflect.Value) error {
12	if v.IsNil() {
13		return e.EncodeNil()
14	}
15
16	if err := e.EncodeMapLen(v.Len()); err != nil {
17		return err
18	}
19
20	for _, key := range v.MapKeys() {
21		if err := e.EncodeValue(key); err != nil {
22			return err
23		}
24		if err := e.EncodeValue(v.MapIndex(key)); err != nil {
25			return err
26		}
27	}
28
29	return nil
30}
31
32func encodeMapStringStringValue(e *Encoder, v reflect.Value) error {
33	if v.IsNil() {
34		return e.EncodeNil()
35	}
36
37	if err := e.EncodeMapLen(v.Len()); err != nil {
38		return err
39	}
40
41	m := v.Convert(mapStringStringType).Interface().(map[string]string)
42	if e.flags&sortMapKeysFlag != 0 {
43		return e.encodeSortedMapStringString(m)
44	}
45
46	for mk, mv := range m {
47		if err := e.EncodeString(mk); err != nil {
48			return err
49		}
50		if err := e.EncodeString(mv); err != nil {
51			return err
52		}
53	}
54
55	return nil
56}
57
58func encodeMapStringInterfaceValue(e *Encoder, v reflect.Value) error {
59	if v.IsNil() {
60		return e.EncodeNil()
61	}
62	m := v.Convert(mapStringInterfaceType).Interface().(map[string]interface{})
63	if e.flags&sortMapKeysFlag != 0 {
64		return e.EncodeMapSorted(m)
65	}
66	return e.EncodeMap(m)
67}
68
69func (e *Encoder) EncodeMap(m map[string]interface{}) error {
70	if m == nil {
71		return e.EncodeNil()
72	}
73	if err := e.EncodeMapLen(len(m)); err != nil {
74		return err
75	}
76	for mk, mv := range m {
77		if err := e.EncodeString(mk); err != nil {
78			return err
79		}
80		if err := e.Encode(mv); err != nil {
81			return err
82		}
83	}
84	return nil
85}
86
87func (e *Encoder) EncodeMapSorted(m map[string]interface{}) error {
88	if m == nil {
89		return e.EncodeNil()
90	}
91	if err := e.EncodeMapLen(len(m)); err != nil {
92		return err
93	}
94
95	keys := make([]string, 0, len(m))
96
97	for k := range m {
98		keys = append(keys, k)
99	}
100
101	sort.Strings(keys)
102
103	for _, k := range keys {
104		if err := e.EncodeString(k); err != nil {
105			return err
106		}
107		if err := e.Encode(m[k]); err != nil {
108			return err
109		}
110	}
111
112	return nil
113}
114
115func (e *Encoder) encodeSortedMapStringString(m map[string]string) error {
116	keys := make([]string, 0, len(m))
117	for k := range m {
118		keys = append(keys, k)
119	}
120	sort.Strings(keys)
121
122	for _, k := range keys {
123		err := e.EncodeString(k)
124		if err != nil {
125			return err
126		}
127		if err = e.EncodeString(m[k]); err != nil {
128			return err
129		}
130	}
131
132	return nil
133}
134
135func (e *Encoder) EncodeMapLen(l int) error {
136	if l < 16 {
137		return e.writeCode(msgpcode.FixedMapLow | byte(l))
138	}
139	if l <= math.MaxUint16 {
140		return e.write2(msgpcode.Map16, uint16(l))
141	}
142	return e.write4(msgpcode.Map32, uint32(l))
143}
144
145func encodeStructValue(e *Encoder, strct reflect.Value) error {
146	structFields := structs.Fields(strct.Type(), e.structTag)
147	if e.flags&arrayEncodedStructsFlag != 0 || structFields.AsArray {
148		return encodeStructValueAsArray(e, strct, structFields.List)
149	}
150	fields := structFields.OmitEmpty(strct, e.flags&omitEmptyFlag != 0)
151
152	if err := e.EncodeMapLen(len(fields)); err != nil {
153		return err
154	}
155
156	for _, f := range fields {
157		if err := e.EncodeString(f.name); err != nil {
158			return err
159		}
160		if err := f.EncodeValue(e, strct); err != nil {
161			return err
162		}
163	}
164
165	return nil
166}
167
168func encodeStructValueAsArray(e *Encoder, strct reflect.Value, fields []*field) error {
169	if err := e.EncodeArrayLen(len(fields)); err != nil {
170		return err
171	}
172	for _, f := range fields {
173		if err := f.EncodeValue(e, strct); err != nil {
174			return err
175		}
176	}
177	return nil
178}
179