go-gun/gun/node.go

124 lines
2.9 KiB
Go
Raw Normal View History

2019-02-20 20:54:46 +00:00
package gun
2019-02-22 06:46:19 +00:00
import (
"bytes"
"encoding/json"
"fmt"
"strconv"
)
2019-02-20 20:54:46 +00:00
2019-02-25 04:23:15 +00:00
func DefaultSoulGen() string {
2019-02-25 05:14:26 +00:00
ms, uniqueNum := timeNowUniqueUnix()
2019-02-20 20:54:46 +00:00
s := strconv.FormatInt(ms, 36)
if uniqueNum > 0 {
s += strconv.FormatInt(uniqueNum, 36)
}
2019-02-22 06:46:19 +00:00
return s + randString(12)
2019-02-20 20:54:46 +00:00
}
type Node struct {
2019-02-22 09:23:14 +00:00
Metadata
2019-02-22 06:46:19 +00:00
Values map[string]Value
}
func (n *Node) MarshalJSON() ([]byte, error) {
// Just put it all in a map and then encode it
toEnc := make(map[string]interface{}, len(n.Values)+1)
2019-02-22 09:23:14 +00:00
toEnc["_"] = &n.Metadata
2019-02-22 06:46:19 +00:00
for k, v := range n.Values {
toEnc[k] = v
}
return json.Marshal(toEnc)
}
func (n *Node) UnmarshalJSON(b []byte) error {
dec := json.NewDecoder(bytes.NewReader(b))
dec.UseNumber()
// We'll just go from start brace to end brace
if t, err := dec.Token(); err != nil {
return err
} else if t != json.Delim('{') {
return fmt.Errorf("Unexpected token %v", t)
}
n.Values = map[string]Value{}
for {
if key, err := dec.Token(); err != nil {
return err
} else if key == json.Delim('}') {
return nil
} else if keyStr, ok := key.(string); !ok {
return fmt.Errorf("Unrecognized token %v", key)
} else if keyStr == "_" {
2019-02-22 09:23:14 +00:00
if err = dec.Decode(&n.Metadata); err != nil {
2019-02-22 06:46:19 +00:00
return fmt.Errorf("Failed unmarshaling metadata: %v", err)
}
} else if val, err := dec.Token(); err != nil {
return err
2019-02-25 05:14:26 +00:00
} else if n.Values[keyStr], err = ValueDecodeJSON(val, dec); err != nil {
2019-02-22 06:46:19 +00:00
return err
}
}
2019-02-20 20:54:46 +00:00
}
2019-02-22 09:23:14 +00:00
type Metadata struct {
Soul string `json:"#,omitempty"`
2019-02-25 05:14:26 +00:00
State map[string]State `json:">,omitempty"`
2019-02-20 20:54:46 +00:00
}
2019-02-22 06:46:19 +00:00
type Value interface {
2019-02-25 05:14:26 +00:00
nodeValue()
2019-02-22 06:46:19 +00:00
}
2019-02-25 05:14:26 +00:00
func ValueDecodeJSON(token json.Token, dec *json.Decoder) (Value, error) {
2019-02-22 06:46:19 +00:00
switch token := token.(type) {
case nil:
return nil, nil
case json.Number:
return ValueNumber(token), nil
case string:
return ValueString(token), nil
case bool:
return ValueBool(token), nil
case json.Delim:
if token != json.Delim('{') {
return nil, fmt.Errorf("Unrecognized token %v", token)
} else if relKey, err := dec.Token(); err != nil {
return nil, err
} else if relKey != "#" {
return nil, fmt.Errorf("Unrecognized token %v", relKey)
} else if relVal, err := dec.Token(); err != nil {
return nil, err
} else if relValStr, ok := relVal.(string); !ok {
return nil, fmt.Errorf("Unrecognized token %v", relVal)
} else if endTok, err := dec.Token(); err != nil {
return nil, err
} else if endTok != json.Delim('}') {
return nil, fmt.Errorf("Unrecognized token %v", endTok)
} else {
return ValueRelation(relValStr), nil
}
default:
return nil, fmt.Errorf("Unrecognized token %v", token)
}
}
type ValueString string
2019-02-25 05:14:26 +00:00
func (ValueString) nodeValue() {}
2019-02-22 06:46:19 +00:00
type ValueNumber string
2019-02-25 05:14:26 +00:00
func (ValueNumber) nodeValue() {}
2019-02-22 06:46:19 +00:00
type ValueBool bool
2019-02-25 05:14:26 +00:00
func (ValueBool) nodeValue() {}
2019-02-22 06:46:19 +00:00
type ValueRelation string
2019-02-20 20:54:46 +00:00
2019-02-25 05:14:26 +00:00
func (ValueRelation) nodeValue() {}
2019-02-22 06:46:19 +00:00
func (n ValueRelation) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]string{"#": string(n)})
2019-02-20 20:54:46 +00:00
}