Skip to content

Commit 8636dde

Browse files
committed
restructured to enable custom types injection on
Marshal and Unmarshal The core is the basic functionality of the map
1 parent d7ddbd2 commit 8636dde

File tree

5 files changed

+323
-305
lines changed

5 files changed

+323
-305
lines changed

go.sum

Whitespace-only changes.

orderedmap-core.go

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
package orderedmap
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"io"
7+
)
8+
9+
type OrderedMapCore interface {
10+
CoreKeys() []string
11+
CoreSetKeys([]string)
12+
CoreValues() map[string]interface{}
13+
CoreSetValues(map[string]interface{})
14+
CoreGetKey(key string) (interface{}, bool)
15+
CoreSetKey(key string, value interface{})
16+
CoreDeleteKey(key string)
17+
}
18+
19+
type CloneFunc func(...map[string]interface{}) OrderedMapCore
20+
21+
type orderedMapCore struct {
22+
keys []string
23+
values map[string]interface{}
24+
}
25+
26+
func NewCore(oms ...map[string]interface{}) OrderedMapCore {
27+
var om map[string]interface{}
28+
if len(oms) > 0 {
29+
om = oms[0]
30+
} else {
31+
om = make(map[string]interface{})
32+
}
33+
return &orderedMapCore{
34+
keys: make([]string, 0, len(om)),
35+
values: om,
36+
}
37+
}
38+
39+
func (o *orderedMapCore) CoreGetKey(key string) (interface{}, bool) {
40+
val, exists := o.values[key]
41+
return val, exists
42+
}
43+
44+
func (o *orderedMapCore) CoreSetKey(key string, value interface{}) {
45+
_, exists := o.values[key]
46+
if !exists {
47+
o.keys = append(o.keys, key)
48+
}
49+
o.values[key] = value
50+
}
51+
52+
func (o *orderedMapCore) CoreDeleteKey(key string) {
53+
// check key is in use
54+
_, ok := o.values[key]
55+
if !ok {
56+
return
57+
}
58+
// remove from keys
59+
for i, k := range o.keys {
60+
if k == key {
61+
o.keys = append(o.keys[:i], o.keys[i+1:]...)
62+
break
63+
}
64+
}
65+
// remove from values
66+
delete(o.values, key)
67+
}
68+
69+
func (o *orderedMapCore) CoreKeys() []string {
70+
return o.keys
71+
}
72+
73+
func (o *orderedMapCore) CoreSetKeys(keys []string) {
74+
o.keys = keys
75+
}
76+
77+
func (o *orderedMapCore) CoreValues() map[string]interface{} {
78+
return o.values
79+
}
80+
81+
func (o *orderedMapCore) CoreSetValues(values map[string]interface{}) {
82+
o.values = values
83+
}
84+
85+
func BoundUnmarshalJSON(o OrderedMapCore, cloneFn CloneFunc, b []byte) error {
86+
if o == nil {
87+
panic("orderedmap: UnmarshalJSON on nil pointer")
88+
}
89+
if o.CoreValues() == nil {
90+
o.CoreSetValues(make(map[string]interface{}))
91+
}
92+
val := o.CoreValues()
93+
err := json.Unmarshal(b, &val)
94+
if err != nil {
95+
return err
96+
}
97+
dec := json.NewDecoder(bytes.NewReader(b))
98+
if _, err = dec.Token(); err != nil { // skip '{'
99+
return err
100+
}
101+
return decodeOrderedMap(dec, o, cloneFn)
102+
}
103+
104+
func BoundMarshalJSON(o OrderedMapCore, encoder *json.Encoder, buf io.Writer) error {
105+
buf.Write([]byte{'{'})
106+
107+
values := o.CoreValues()
108+
for i, k := range o.CoreKeys() {
109+
if i > 0 {
110+
buf.Write([]byte{','})
111+
}
112+
// add key
113+
if err := encoder.Encode(k); err != nil {
114+
return err
115+
}
116+
buf.Write([]byte{':'})
117+
// add value
118+
if err := encoder.Encode(values[k]); err != nil {
119+
return err
120+
}
121+
}
122+
buf.Write([]byte{'}'})
123+
return nil
124+
}
125+
126+
func decodeOrderedMap(dec *json.Decoder, o OrderedMapCore, cloneFn CloneFunc) error {
127+
vals := o.CoreValues()
128+
hasKey := make(map[string]bool, len(vals))
129+
for {
130+
token, err := dec.Token()
131+
if err != nil {
132+
return err
133+
}
134+
if delim, ok := token.(json.Delim); ok && delim == '}' {
135+
return nil
136+
}
137+
key := token.(string)
138+
if hasKey[key] {
139+
// duplicate key
140+
for j, k := range o.CoreKeys() {
141+
if k == key {
142+
copy(o.CoreKeys()[j:], o.CoreKeys()[j+1:])
143+
break
144+
}
145+
}
146+
o.CoreKeys()[len(o.CoreKeys())-1] = key
147+
} else {
148+
hasKey[key] = true
149+
o.CoreSetKeys(append(o.CoreKeys(), key))
150+
}
151+
152+
token, err = dec.Token()
153+
if err != nil {
154+
return err
155+
}
156+
if delim, ok := token.(json.Delim); ok {
157+
switch delim {
158+
case '{':
159+
if values, ok := vals[key].(map[string]interface{}); ok {
160+
newMap := cloneFn(values)
161+
if err = decodeOrderedMap(dec, newMap, cloneFn); err != nil {
162+
return err
163+
}
164+
vals[key] = newMap
165+
} else if oldMap, ok := vals[key].(OrderedMap); ok {
166+
newMap := cloneFn(oldMap.Values())
167+
if err = decodeOrderedMap(dec, newMap, cloneFn); err != nil {
168+
return err
169+
}
170+
vals[key] = newMap
171+
} else if err = decodeOrderedMap(dec, cloneFn(), cloneFn); err != nil {
172+
return err
173+
}
174+
case '[':
175+
if values, ok := vals[key].([]interface{}); ok {
176+
if err = decodeSlice(dec, values, o, cloneFn); err != nil {
177+
return err
178+
}
179+
} else if err = decodeSlice(dec, []interface{}{}, o, cloneFn); err != nil {
180+
return err
181+
}
182+
}
183+
}
184+
}
185+
}
186+
187+
func decodeSlice(dec *json.Decoder, s []interface{}, o OrderedMapCore, cloneFn CloneFunc) error {
188+
for index := 0; ; index++ {
189+
token, err := dec.Token()
190+
if err != nil {
191+
return err
192+
}
193+
if delim, ok := token.(json.Delim); ok {
194+
switch delim {
195+
case '{':
196+
if index < len(s) {
197+
if values, ok := s[index].(map[string]interface{}); ok {
198+
newMap := cloneFn(values)
199+
if err = decodeOrderedMap(dec, newMap, cloneFn); err != nil {
200+
return err
201+
}
202+
s[index] = newMap
203+
} else if oldMap, ok := s[index].(OrderedMap); ok {
204+
newMap := cloneFn(oldMap.Values())
205+
if err = decodeOrderedMap(dec, newMap, cloneFn); err != nil {
206+
return err
207+
}
208+
s[index] = newMap
209+
} else if err = decodeOrderedMap(dec, cloneFn(), cloneFn); err != nil {
210+
return err
211+
}
212+
} else if err = decodeOrderedMap(dec, cloneFn(), cloneFn); err != nil {
213+
return err
214+
}
215+
case '[':
216+
if index < len(s) {
217+
if values, ok := s[index].([]interface{}); ok {
218+
if err = decodeSlice(dec, values, o, cloneFn); err != nil {
219+
return err
220+
}
221+
} else if err = decodeSlice(dec, []interface{}{}, o, cloneFn); err != nil {
222+
return err
223+
}
224+
} else if err = decodeSlice(dec, []interface{}{}, o, cloneFn); err != nil {
225+
return err
226+
}
227+
case ']':
228+
return nil
229+
}
230+
}
231+
}
232+
}

0 commit comments

Comments
 (0)