| 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..406d14ee4eb2f9631e8b3e6b9ffa12beab8f18e4
 | 
| --- /dev/null
 | 
| +++ b/go/src/infra/gae/libs/wrapper/memory/internal/goon/goon.go
 | 
| @@ -0,0 +1,103 @@
 | 
| +/*
 | 
| + * 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"
 | 
| +)
 | 
| +
 | 
| +// copied from goon since it's internal and we need it for 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
 | 
| +}
 | 
| 
 |