Esempio n. 1
0
// TODO(riannucci): dedup with datastore/key testing file.
func mkKey(aid, ns string, elems ...interface{}) ds.Key {
	if len(elems)%2 != 0 {
		panic("odd number of tokens")
	}
	toks := make([]ds.KeyTok, len(elems)/2)
	for i := 0; i < len(elems); i += 2 {
		toks[i/2].Kind = elems[i].(string)
		switch x := elems[i+1].(type) {
		case string:
			toks[i/2].StringID = x
		case int:
			toks[i/2].IntID = int64(x)
		default:
			panic("bad token id")
		}
	}
	return dskey.NewToks(aid, ns, toks)
}
Esempio n. 2
0
// ReadKey deserializes a key from the buffer. The value of context must match
// the value of context that was passed to WriteKey when the key was encoded.
// If context == WithoutContext, then the appid and namespace parameters are
// used in the decoded Key. Otherwise they're ignored.
func ReadKey(buf Buffer, context KeyContext, appid, namespace string) (ret ds.Key, err error) {
	defer recoverTo(&err)
	actualCtx, e := buf.ReadByte()
	panicIf(e)

	actualAid, actualNS := "", ""
	if actualCtx == 1 {
		actualAid, _, e = cmpbin.ReadString(buf)
		panicIf(e)
		actualNS, _, e = cmpbin.ReadString(buf)
		panicIf(e)
	} else if actualCtx != 0 {
		err = fmt.Errorf("helper: expected actualCtx to be 0 or 1, got %d", actualCtx)
		return
	}

	if context == WithoutContext {
		// overrwrite with the supplied ones
		actualAid = appid
		actualNS = namespace
	}

	toks := []ds.KeyTok{}
	for {
		ctrlByte, e := buf.ReadByte()
		panicIf(e)
		if ctrlByte == 0 {
			break
		}
		if len(toks)+1 > ReadKeyNumToksReasonableLimit {
			err = fmt.Errorf(
				"helper: tried to decode huge key with > %d tokens",
				ReadKeyNumToksReasonableLimit)
			return
		}

		tok, e := ReadKeyTok(buf)
		panicIf(e)

		toks = append(toks, tok)
	}

	return dskey.NewToks(actualAid, actualNS, toks), nil
}
func maybeIndexValue(val interface{}) interface{} {
	// It may be the SDK's datastore.indexValue structure (in datastore/load.go).
	//
	// Since this is a private type with no methods, we need to use reflection
	// to get the data out. Ick.
	rv := reflect.ValueOf(val)
	if rv.Kind() == reflect.Struct && rv.Type().String() == "datastore.indexValue" {
		rv = rv.FieldByName("value")
		if rv.IsValid() && rv.Kind() == reflect.Ptr {
			// TODO(riannucci): determine if this is how nil IndexValues are stored.
			// Maybe they're encoded as a PropertyValue with all-nil fields instead?
			if rv.IsNil() {
				return nil
			}
			rv = rv.Elem()
			// we're in protobuf land now.
			if rv.Type().Name() == "PropertyValue" {
				for i := 0; i < rv.NumField(); i++ {
					field := rv.Field(i)
					if field.Kind() == reflect.Ptr {
						if field.IsNil() {
							continue
						}
						field = field.Elem()
						switch field.Kind() {
						case reflect.Int64:
							return field.Int()
						case reflect.String:
							return field.String()
						case reflect.Bool:
							return field.Bool()
						case reflect.Float64:
							return field.Float()
						}
						switch field.Type().Name() {
						case "PropertyValue_PointValue":
							// Lat == X, Lng == Y b/c historical resons.
							return ds.GeoPoint{
								Lat: field.FieldByName("X").Float(),
								Lng: field.FieldByName("Y").Float()}
						case "PropertyValue_ReferenceValue":
							aid := field.FieldByName("App").Elem().String()
							ns := ""
							if nsf := field.FieldByName("NameSpace"); !nsf.IsNil() {
								ns = nsf.Elem().String()
							}
							elems := field.FieldByName("Pathelement")
							toks := make([]ds.KeyTok, elems.Len())
							for i := range toks {
								e := elems.Index(i).Elem()
								toks[i].Kind = e.FieldByName("Type").Elem().String()
								if iid := e.FieldByName("Id"); !iid.IsNil() {
									toks[i].IntID = iid.Elem().Int()
								}
								if sid := e.FieldByName("Name"); !sid.IsNil() {
									toks[i].StringID = sid.Elem().String()
								}
							}
							return dskey.NewToks(aid, ns, toks)
						}
						panic(fmt.Errorf(
							"UNKNOWN datastore.indexValue field type: %s", field.Type()))
					}
					// there's also the `XXX_unrecognized []byte` field, so don't panic
					// here.
				}
				panic(fmt.Errorf("cannot decode datastore.indexValue (no recognized field): %v", val))
			}
			panic(fmt.Errorf("cannot decode datastore.indexValue (wrong inner type): %v", val))
		}
		panic(fmt.Errorf("cannot decode datastore.indexValue: %v", val))
	} else {
		return val
	}
}