Index: go/src/infra/gae/libs/wrapper/memory/internal/goon/goon.go |
diff --git a/go/src/infra/gae/libs/wrapper/memory/internal/goon/goon.go b/go/src/infra/gae/libs/wrapper/memory/internal/goon/goon.go |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7ddee8b654848279c1fe63ab0fb706e25173cca8 |
--- /dev/null |
+++ b/go/src/infra/gae/libs/wrapper/memory/internal/goon/goon.go |
@@ -0,0 +1,104 @@ |
+/* |
+ * Copyright (c) 2012 Matt Jibson <matt.jibson@gmail.com> |
+ * |
+ * Permission to use, copy, modify, and distribute this software for any |
+ * purpose with or without fee is hereby granted, provided that the above |
+ * copyright notice and this permission notice appear in all copies. |
+ * |
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
+ */ |
+ |
+package goon |
+ |
+import ( |
+ "fmt" |
+ "reflect" |
+ "strings" |
+ |
+ "appengine/datastore" |
+ |
+ "github.com/mjibson/goon" |
+) |
+ |
+// SetStructKey assigns a datastore.Key into a goon-style struct. |
+// Copied from goon since it's internal and we need to populate the completed |
+// key after a Datastore.Put() |
+func SetStructKey(src interface{}, key *datastore.Key, knr goon.KindNameResolver) error { |
+ v := reflect.ValueOf(src) |
+ t := v.Type() |
+ k := t.Kind() |
+ |
+ if k != reflect.Ptr { |
+ return fmt.Errorf("goon: Expected pointer to struct, got instead: %v", k) |
+ } |
+ |
+ v = reflect.Indirect(v) |
+ t = v.Type() |
+ k = t.Kind() |
+ |
+ if k != reflect.Struct { |
+ return fmt.Errorf(fmt.Sprintf("goon: Expected struct, got instead: %v", k)) |
+ } |
+ |
+ idSet := false |
+ kindSet := false |
+ parentSet := false |
+ for i := 0; i < v.NumField(); i++ { |
+ tf := t.Field(i) |
+ vf := v.Field(i) |
+ |
+ if !vf.CanSet() { |
+ continue |
+ } |
+ |
+ tag := tf.Tag.Get("goon") |
+ tagValues := strings.Split(tag, ",") |
+ if len(tagValues) > 0 { |
+ tagValue := tagValues[0] |
+ if tagValue == "id" { |
+ if idSet { |
+ return fmt.Errorf("goon: Only one field may be marked id") |
+ } |
+ |
+ switch vf.Kind() { |
+ case reflect.Int64: |
+ vf.SetInt(key.IntID()) |
+ idSet = true |
+ case reflect.String: |
+ vf.SetString(key.StringID()) |
+ idSet = true |
+ } |
+ } else if tagValue == "kind" { |
+ if kindSet { |
+ return fmt.Errorf("goon: Only one field may be marked kind") |
+ } |
+ if vf.Kind() == reflect.String { |
+ if (len(tagValues) <= 1 || key.Kind() != tagValues[1]) && knr(src) != key.Kind() { |
+ vf.Set(reflect.ValueOf(key.Kind())) |
+ } |
+ kindSet = true |
+ } |
+ } else if tagValue == "parent" { |
+ if parentSet { |
+ return fmt.Errorf("goon: Only one field may be marked parent") |
+ } |
+ if vf.Type() == reflect.TypeOf(&datastore.Key{}) { |
+ vf.Set(reflect.ValueOf(key.Parent())) |
+ parentSet = true |
+ } |
+ } |
+ } |
+ } |
+ |
+ if !idSet { |
+ return fmt.Errorf("goon: Could not set id field") |
+ } |
+ |
+ return nil |
+} |