summaryrefslogtreecommitdiff
path: root/serial.go
diff options
context:
space:
mode:
Diffstat (limited to 'serial.go')
-rw-r--r--serial.go94
1 files changed, 94 insertions, 0 deletions
diff --git a/serial.go b/serial.go
new file mode 100644
index 0000000..59a3118
--- /dev/null
+++ b/serial.go
@@ -0,0 +1,94 @@
+package serial
+
+import (
+ "io"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+type Encoder struct {
+ w io.Writer
+ wg sync.WaitGroup
+ groups []string
+}
+
+func (e *Encoder) Encode(entity interface{}) error {
+ t := reflect.TypeOf(entity)
+ v := reflect.ValueOf(entity)
+ if err := e.encodeField(t, v, e.w); err != nil {
+ return err
+ }
+ return nil
+}
+func (e *Encoder) encodeAny(entity interface{}, w io.Writer) error {
+ t := reflect.TypeOf(entity)
+ v := reflect.ValueOf(entity)
+ first := true
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ fv := v.Field(i)
+ if gr, ok := f.Tag.Lookup("group"); ok {
+ groups := strings.Split(gr, ",")
+ name := f.Name
+ if tname, ok := f.Tag.Lookup("json"); ok {
+ name = tname
+ }
+ if name != "-" && e.intersect(groups, e.groups) {
+ if !first {
+ w.Write([]byte(`,`))
+ }
+ w.Write([]byte(`"` + name + `":`))
+ e.encodeField(f.Type, fv, w)
+ first = false
+ }
+ }
+ }
+ return nil
+}
+
+func (e *Encoder) intersect(a []string, b []string) bool {
+ for _, sa := range a {
+ for _, sb := range b {
+ if sa == sb {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+func (e *Encoder) encodeField(ft reflect.Type, v reflect.Value, w io.Writer) error {
+ switch ft.Kind() {
+ case reflect.Struct:
+ w.Write([]byte("{"))
+ if err := e.encodeAny(v.Interface(), w); err != nil {
+ return err
+ }
+ w.Write([]byte("}"))
+ case reflect.String:
+ w.Write([]byte(`"` + v.String() + `"`))
+ case reflect.Bool:
+ if v.Bool() {
+ w.Write([]byte("true"))
+ } else {
+ w.Write([]byte("false"))
+ }
+ case reflect.Int, reflect.Int32, reflect.Int64:
+ w.Write([]byte(strconv.Itoa(int(v.Int()))))
+ case reflect.Float32, reflect.Float64:
+ w.Write([]byte(strconv.FormatFloat(v.Float(), 'f', -1, 64)))
+
+ }
+ return nil
+}
+
+func (e *Encoder) AddGroup(group string) *Encoder {
+ e.groups = append(e.groups, group)
+ return e
+}
+
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{w: w, groups: []string{}}
+}