summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/gopackage/ddp/ddp_ejson.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/gopackage/ddp/ddp_ejson.go')
-rw-r--r--vendor/github.com/gopackage/ddp/ddp_ejson.go217
1 files changed, 217 insertions, 0 deletions
diff --git a/vendor/github.com/gopackage/ddp/ddp_ejson.go b/vendor/github.com/gopackage/ddp/ddp_ejson.go
new file mode 100644
index 00000000..a3e1fec0
--- /dev/null
+++ b/vendor/github.com/gopackage/ddp/ddp_ejson.go
@@ -0,0 +1,217 @@
+package ddp
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+ "io"
+ "strings"
+ "time"
+)
+
+// ----------------------------------------------------------------------
+// EJSON document interface
+// ----------------------------------------------------------------------
+// https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md#appendix-ejson
+
+// Doc provides hides the complexity of ejson documents.
+type Doc struct {
+ root interface{}
+}
+
+// NewDoc creates a new document from a generic json parsed document.
+func NewDoc(in interface{}) *Doc {
+ doc := &Doc{in}
+ return doc
+}
+
+// Map locates a map[string]interface{} - json object - at a path
+// or returns nil if not found.
+func (d *Doc) Map(path string) map[string]interface{} {
+ item := d.Item(path)
+ if item != nil {
+ switch m := item.(type) {
+ case map[string]interface{}:
+ return m
+ default:
+ return nil
+ }
+ }
+ return nil
+}
+
+// Array locates an []interface{} - json array - at a path
+// or returns nil if not found.
+func (d *Doc) Array(path string) []interface{} {
+ item := d.Item(path)
+ if item != nil {
+ switch m := item.(type) {
+ case []interface{}:
+ return m
+ default:
+ return nil
+ }
+ }
+ return nil
+}
+
+// StringArray locates an []string - json array of strings - at a path
+// or returns nil if not found. The string array will contain all string values
+// in the array and skip any non-string entries.
+func (d *Doc) StringArray(path string) []string {
+ item := d.Item(path)
+ if item != nil {
+ switch m := item.(type) {
+ case []interface{}:
+ items := []string{}
+ for _, item := range m {
+ switch val := item.(type) {
+ case string:
+ items = append(items, val)
+ }
+ }
+ return items
+ case []string:
+ return m
+ default:
+ return nil
+ }
+ }
+ return nil
+}
+
+// String returns a string value located at the path or an empty string if not found.
+func (d *Doc) String(path string) string {
+ item := d.Item(path)
+ if item != nil {
+ switch m := item.(type) {
+ case string:
+ return m
+ default:
+ return ""
+ }
+ }
+ return ""
+}
+
+// Bool returns a boolean value located at the path or false if not found.
+func (d *Doc) Bool(path string) bool {
+ item := d.Item(path)
+ if item != nil {
+ switch m := item.(type) {
+ case bool:
+ return m
+ default:
+ return false
+ }
+ }
+ return false
+}
+
+// Float returns a float64 value located at the path or zero if not found.
+func (d *Doc) Float(path string) float64 {
+ item := d.Item(path)
+ if item != nil {
+ switch m := item.(type) {
+ case float64:
+ return m
+ default:
+ return 0
+ }
+ }
+ return 0
+}
+
+// Time returns a time value located at the path or nil if not found.
+func (d *Doc) Time(path string) time.Time {
+ ticks := d.Float(path + ".$date")
+ var t time.Time
+ if ticks > 0 {
+ sec := int64(ticks / 1000)
+ t = time.Unix(int64(sec), 0)
+ }
+ return t
+}
+
+// Item locates a "raw" item at the provided path, returning
+// the item found or nil if not found.
+func (d *Doc) Item(path string) interface{} {
+ item := d.root
+ steps := strings.Split(path, ".")
+ for _, step := range steps {
+ // This is an intermediate step - we must be in a map
+ switch m := item.(type) {
+ case map[string]interface{}:
+ item = m[step]
+ case Update:
+ item = m[step]
+ default:
+ return nil
+ }
+ }
+ return item
+}
+
+// Set a value for a path. Intermediate items are created as necessary.
+func (d *Doc) Set(path string, value interface{}) {
+ item := d.root
+ steps := strings.Split(path, ".")
+ last := steps[len(steps)-1]
+ steps = steps[:len(steps)-1]
+ for _, step := range steps {
+ // This is an intermediate step - we must be in a map
+ switch m := item.(type) {
+ case map[string]interface{}:
+ item = m[step]
+ if item == nil {
+ item = map[string]interface{}{}
+ m[step] = item
+ }
+ default:
+ return
+ }
+ }
+ // Item is now the last map so we just set the value
+ switch m := item.(type) {
+ case map[string]interface{}:
+ m[last] = value
+ }
+}
+
+// Accounts password login support
+type Login struct {
+ User *User `json:"user"`
+ Password *Password `json:"password"`
+}
+
+func NewEmailLogin(email, pass string) *Login {
+ return &Login{User: &User{Email: email}, Password: NewPassword(pass)}
+}
+
+func NewUsernameLogin(user, pass string) *Login {
+ return &Login{User: &User{Username: user}, Password: NewPassword(pass)}
+}
+
+type LoginResume struct {
+ Token string `json:"resume"`
+}
+
+func NewLoginResume(token string) *LoginResume {
+ return &LoginResume{Token: token}
+}
+
+type User struct {
+ Email string `json:"email,omitempty"`
+ Username string `json:"username,omitempty"`
+}
+
+type Password struct {
+ Digest string `json:"digest"`
+ Algorithm string `json:"algorithm"`
+}
+
+func NewPassword(pass string) *Password {
+ sha := sha256.New()
+ io.WriteString(sha, pass)
+ digest := sha.Sum(nil)
+ return &Password{Digest: hex.EncodeToString(digest), Algorithm: "sha-256"}
+}