// ReadKeyTok reads a KeyTok from the buffer. You usually want ReadKey // instead of this. func ReadKeyTok(buf Buffer) (ret ds.KeyTok, err error) { defer recoverTo(&err) e := error(nil) ret.Kind, _, e = cmpbin.ReadString(buf) panicIf(e) typ, e := buf.ReadByte() panicIf(e) switch ds.PropertyType(typ) { case ds.PTString: ret.StringID, _, err = cmpbin.ReadString(buf) case ds.PTInt: ret.IntID, _, err = cmpbin.ReadInt(buf) if err == nil && ret.IntID <= 0 { err = errors.New("helper: decoded key with empty stringID and zero/negative intID") } default: err = fmt.Errorf("helper: invalid type %s", ds.PropertyType(typ)) } return }
// ReadProperty reads a Property from the buffer. `context`, `appid`, and // `namespace` behave the same way they do for ReadKey, but only have an // effect if the decoded property has a Key value. func ReadProperty(buf Buffer, context KeyContext, appid, namespace string) (p ds.Property, err error) { val := interface{}(nil) b, err := buf.ReadByte() if err != nil { return } is := ds.ShouldIndex if (b & 0x80) == 0 { is = ds.NoIndex } switch ds.PropertyType(b & 0x7f) { case ds.PTNull: case ds.PTBool: b, err = buf.ReadByte() val = (b != 0) case ds.PTInt: val, _, err = cmpbin.ReadInt(buf) case ds.PTFloat: val, _, err = cmpbin.ReadFloat64(buf) case ds.PTString: val, _, err = cmpbin.ReadString(buf) case ds.PTBytes: val, _, err = cmpbin.ReadBytes(buf) case ds.PTTime: val, err = ReadTime(buf) case ds.PTGeoPoint: val, err = ReadGeoPoint(buf) case ds.PTKey: val, err = ReadKey(buf, context, appid, namespace) case ds.PTBlobKey: s := "" if s, _, err = cmpbin.ReadString(buf); err != nil { break } val = blobstore.Key(s) default: err = fmt.Errorf("read: unknown type! %v", b) } if err == nil { err = p.SetValue(val, is) } return }