Skip to content

Commit 0d1a893

Browse files
authored
Merge pull request #68 from francoispqt/afiune-afiune/add-interface-decoder
Afiune afiune/add interface decoder
2 parents 491f8af + a123dc0 commit 0d1a893

File tree

7 files changed

+692
-4
lines changed

7 files changed

+692
-4
lines changed

decode.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ func Unmarshal(data []byte, v interface{}) error {
215215
dec.data = make([]byte, len(data))
216216
copy(dec.data, data)
217217
_, err = dec.decodeArray(vt)
218+
case *interface{}:
219+
dec = borrowDecoder(nil, 0)
220+
dec.length = len(data)
221+
dec.data = make([]byte, len(data))
222+
copy(dec.data, data)
223+
err = dec.decodeInterface(vt)
218224
default:
219225
return InvalidUnmarshalError(fmt.Sprintf(invalidUnmarshalErrorMsg, reflect.TypeOf(vt).String()))
220226
}
@@ -318,6 +324,8 @@ func (dec *Decoder) Decode(v interface{}) error {
318324
_, err = dec.decodeArray(vt)
319325
case *EmbeddedJSON:
320326
err = dec.decodeEmbeddedJSON(vt)
327+
case *interface{}:
328+
err = dec.decodeInterface(vt)
321329
default:
322330
return InvalidUnmarshalError(fmt.Sprintf(invalidUnmarshalErrorMsg, reflect.TypeOf(vt).String()))
323331
}
@@ -523,6 +531,11 @@ func (dec *Decoder) AddArray(v UnmarshalerJSONArray) error {
523531
return dec.Array(v)
524532
}
525533

534+
// AddInterface decodes the next key to a interface{}.
535+
func (dec *Decoder) AddInterface(v *interface{}) error {
536+
return dec.Interface(v)
537+
}
538+
526539
// Int decodes the next key to an *int.
527540
// If next key value overflows int, an InvalidUnmarshalError error will be returned.
528541
func (dec *Decoder) Int(v *int) error {
@@ -868,6 +881,16 @@ func (dec *Decoder) Array(value UnmarshalerJSONArray) error {
868881
return nil
869882
}
870883

884+
// Interface decodes the next key to an interface{}.
885+
func (dec *Decoder) Interface(value *interface{}) error {
886+
err := dec.decodeInterface(value)
887+
if err != nil {
888+
return err
889+
}
890+
dec.called |= 1
891+
return nil
892+
}
893+
871894
// Non exported
872895

873896
func isDigit(b byte) bool {

decode_interface.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package gojay
2+
3+
// TODO @afiune for now we are using the standard json unmarshaling but in
4+
// the future it would be great to implement one here inside this repo
5+
import (
6+
"encoding/json"
7+
)
8+
9+
// DecodeInterface reads the next JSON-encoded value from its input and stores it in the value pointed to by i.
10+
//
11+
// i must be an interface poiter
12+
func (dec *Decoder) DecodeInterface(i *interface{}) error {
13+
if dec.isPooled == 1 {
14+
panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
15+
}
16+
err := dec.decodeInterface(i)
17+
return err
18+
}
19+
20+
func (dec *Decoder) decodeInterface(i *interface{}) error {
21+
start, end, err := dec.getObject()
22+
if err != nil {
23+
dec.cursor = start
24+
return err
25+
}
26+
27+
// if start & end are equal the object is a null, don't unmarshal
28+
if start == end {
29+
return nil
30+
}
31+
32+
object := dec.data[start:end]
33+
if err = json.Unmarshal(object, i); err != nil {
34+
return err
35+
}
36+
37+
dec.cursor = end
38+
return nil
39+
}
40+
41+
// @afiune Maybe return the type as well?
42+
func (dec *Decoder) getObject() (start int, end int, err error) {
43+
// start cursor
44+
start = dec.cursor
45+
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
46+
switch dec.data[dec.cursor] {
47+
case ' ', '\n', '\t', '\r', ',':
48+
continue
49+
// is null
50+
case 'n':
51+
dec.cursor++
52+
err = dec.assertNull()
53+
if err != nil {
54+
return
55+
}
56+
// Set start & end to the same cursor to indicate the object
57+
// is a null and should not be unmarshal
58+
start = dec.cursor
59+
end = dec.cursor
60+
dec.cursor++
61+
return
62+
case 't':
63+
dec.cursor++
64+
err = dec.assertTrue()
65+
if err != nil {
66+
return
67+
}
68+
end = dec.cursor
69+
dec.cursor++
70+
return
71+
// is false
72+
case 'f':
73+
dec.cursor++
74+
err = dec.assertFalse()
75+
if err != nil {
76+
return
77+
}
78+
end = dec.cursor
79+
dec.cursor++
80+
return
81+
// is an object
82+
case '{':
83+
dec.cursor++
84+
end, err = dec.skipObject()
85+
dec.cursor = end
86+
return
87+
// is string
88+
case '"':
89+
dec.cursor++
90+
start, end, err = dec.getString()
91+
start--
92+
dec.cursor = end
93+
return
94+
// is array
95+
case '[':
96+
dec.cursor++
97+
end, err = dec.skipArray()
98+
dec.cursor = end
99+
return
100+
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
101+
end, err = dec.skipNumber()
102+
dec.cursor = end
103+
return
104+
default:
105+
err = dec.raiseInvalidJSONErr(dec.cursor)
106+
return
107+
}
108+
}
109+
err = dec.raiseInvalidJSONErr(dec.cursor)
110+
return
111+
}

0 commit comments

Comments
 (0)