-
Notifications
You must be signed in to change notification settings - Fork 16
/
object.go
executable file
·112 lines (96 loc) · 2.01 KB
/
object.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package trap
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"strconv"
"github.com/xhd2015/xgo/runtime/core"
)
// TODO: implement JSON.marshal on func,chan types
type object []field
type field struct {
name string
valPtr interface{}
}
type objectWithErr struct {
object
err field
}
var _ core.Object = (object)(nil)
var _ core.ObjectWithErr = (*objectWithErr)(nil)
var _ core.Field = field{}
func appendFields(obj object, ptrs []interface{}, names []string) object {
for i, arg := range ptrs {
var argName string
if i < len(names) {
argName = names[i]
}
obj = append(obj, field{
name: argName,
valPtr: arg,
})
}
return obj
}
func (c object) GetField(name string) core.Field {
for _, field := range c {
if field.name == name {
return field
}
}
panic(fmt.Errorf("no field: %s", name))
}
func (c object) GetFieldIndex(i int) core.Field {
return c[i]
}
func (c object) NumField() int {
return len(c)
}
func (c *objectWithErr) GetErr() core.Field {
return c.err
}
func (c field) Name() string {
return c.name
}
func (c field) Set(val interface{}) {
// if val is nil, then reflect.ValueOf(val)
// is invalid
if val == nil {
// clear
reflect.ValueOf(c.valPtr).Elem().Set(reflect.Zero(reflect.TypeOf(c.valPtr).Elem()))
return
}
reflect.ValueOf(c.valPtr).Elem().Set(reflect.ValueOf(val))
}
func (c field) Ptr() interface{} {
return c.valPtr
}
func (c field) Value() interface{} {
return reflect.ValueOf(c.valPtr).Elem().Interface()
}
func (c object) MarshalJSON() ([]byte, error) {
if c == nil {
return []byte("null"), nil
}
var buf bytes.Buffer
buf.WriteRune('{')
for i, field := range c {
name := field.name
if name == "" {
name = "field_" + strconv.FormatInt(int64(i), 10)
}
buf.WriteString(strconv.Quote(name))
buf.WriteRune(':')
val, err := json.Marshal(field.valPtr)
if err != nil {
return nil, fmt.Errorf("field %s: %w", name, err)
}
buf.Write(val)
if i < len(c)-1 {
buf.WriteRune(',')
}
}
buf.WriteRune('}')
return buf.Bytes(), nil
}