Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Unified Diff: service/datastore/serialize/serialize.go

Issue 1550903002: impl/memory: Fix time serialization encoding. (Closed) Base URL: https://github.com/luci/gae@master
Patch Set: Comments, tune-up. Created 4 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « service/datastore/properties_test.go ('k') | service/datastore/serialize/serialize_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/serialize/serialize.go
diff --git a/service/datastore/serialize/serialize.go b/service/datastore/serialize/serialize.go
index 736010820f222499212728ca30154029a905cc4f..baa6e3280fdfd456cf8ebb8212dbd1faa052734f 100644
--- a/service/datastore/serialize/serialize.go
+++ b/service/datastore/serialize/serialize.go
@@ -189,16 +189,17 @@ func ReadGeoPoint(buf Buffer) (gp ds.GeoPoint, err error) {
return
}
-// WriteTime writes a time.Time in a byte-sortable way.
+// WriteTime writes a time.Time to the buffer.
//
-// This method truncates the time to microseconds and drops the timezone,
-// because that's the (undocumented) way that the appengine SDK does it.
+// The supplied time is rounded via datastore.RoundTime and written as a
+// microseconds-since-epoch integer to comform to datastore storage standards.
func WriteTime(buf Buffer, t time.Time) error {
name, off := t.Zone()
if name != "UTC" || off != 0 {
panic(fmt.Errorf("helper: UTC OR DEATH: %s", t))
}
- _, err := cmpbin.WriteInt(buf, t.Unix()*1e6+int64(t.Nanosecond()/1e3))
+
+ _, err := cmpbin.WriteInt(buf, ds.TimeToInt(t))
return err
}
@@ -208,48 +209,70 @@ func ReadTime(buf Buffer) (time.Time, error) {
if err != nil {
return time.Time{}, err
}
- t := time.Unix(v/1e6, (v%1e6)*1e3)
- if t.IsZero() {
- return time.Time{}, nil
- }
- return t.UTC(), nil
+ return ds.IntToTime(v), nil
}
// WriteProperty writes a Property to the buffer. `context` behaves the same
// way that it does for WriteKey, but only has an effect if `p` contains a
-// Key as its Value.
-func WriteProperty(buf Buffer, context KeyContext, p ds.Property) (err error) {
+// Key as its IndexValue.
+func WriteProperty(buf Buffer, context KeyContext, p ds.Property) error {
+ return writePropertyImpl(buf, context, &p, false)
+}
+
+// WriteIndexProperty writes a Property to the buffer as its native index type.
+// `context` behaves the same way that it does for WriteKey, but only has an
+// effect if `p` contains a Key as its IndexValue.
+func WriteIndexProperty(buf Buffer, context KeyContext, p ds.Property) error {
+ return writePropertyImpl(buf, context, &p, true)
+}
+
+// writePropertyImpl is an implementation of WriteProperty and
+// WriteIndexProperty.
+func writePropertyImpl(buf Buffer, context KeyContext, p *ds.Property, index bool) (err error) {
defer recoverTo(&err)
- typb := byte(p.Type())
+
+ it, v := p.IndexTypeAndValue()
+ if !index {
+ it = p.Type()
+ }
+ typb := byte(it)
if p.IndexSetting() != ds.NoIndex {
typb |= 0x80
}
panicIf(buf.WriteByte(typb))
- switch p.Type() {
- case ds.PTNull:
- case ds.PTBool:
- b := p.Value().(bool)
- if b {
- err = buf.WriteByte(1)
- } else {
- err = buf.WriteByte(0)
+
+ err = writeIndexValue(buf, context, v)
+ return
+}
+
+// writeIndexValue writes the index value of v to buf.
+//
+// v may be one of the return types from ds.Property's GetIndexTypeAndValue
+// method.
+func writeIndexValue(buf Buffer, context KeyContext, v interface{}) (err error) {
+ switch t := v.(type) {
+ case nil:
+ case bool:
+ b := byte(0)
+ if t {
+ b = 1
}
- case ds.PTInt:
- _, err = cmpbin.WriteInt(buf, p.Value().(int64))
- case ds.PTFloat:
- _, err = cmpbin.WriteFloat64(buf, p.Value().(float64))
- case ds.PTString:
- _, err = cmpbin.WriteString(buf, p.Value().(string))
- case ds.PTBytes:
- _, err = cmpbin.WriteBytes(buf, p.Value().([]byte))
- case ds.PTTime:
- err = WriteTime(buf, p.Value().(time.Time))
- case ds.PTGeoPoint:
- err = WriteGeoPoint(buf, p.Value().(ds.GeoPoint))
- case ds.PTKey:
- err = WriteKey(buf, context, p.Value().(*ds.Key))
- case ds.PTBlobKey:
- _, err = cmpbin.WriteString(buf, string(p.Value().(blobstore.Key)))
+ err = buf.WriteByte(b)
+ case int64:
+ _, err = cmpbin.WriteInt(buf, t)
+ case float64:
+ _, err = cmpbin.WriteFloat64(buf, t)
+ case string:
+ _, err = cmpbin.WriteString(buf, t)
+ case []byte:
+ _, err = cmpbin.WriteBytes(buf, t)
+ case ds.GeoPoint:
+ err = WriteGeoPoint(buf, t)
+ case *ds.Key:
+ err = WriteKey(buf, context, t)
+
+ default:
+ err = fmt.Errorf("unsupported type: %T", t)
}
return
}
@@ -301,11 +324,12 @@ func ReadProperty(buf Buffer, context KeyContext, appid, namespace string) (p ds
return
}
-// WritePropertyMap writes an entire PropertyMap to the buffer. `context` behaves the same
-// way that it does for WriteKey. If WritePropertyMapDeterministic is true, then
-// the rows will be sorted by property name before they're serialized to buf
-// (mostly useful for testing, but also potentially useful if you need to make
-// a hash of the property data).
+// WritePropertyMap writes an entire PropertyMap to the buffer. `context`
+// behaves the same way that it does for WriteKey.
+//
+// If WritePropertyMapDeterministic is true, then the rows will be sorted by
+// property name before they're serialized to buf (mostly useful for testing,
+// but also potentially useful if you need to make a hash of the property data).
//
// Write skips metadata keys.
func WritePropertyMap(buf Buffer, context KeyContext, pm ds.PropertyMap) (err error) {
@@ -466,7 +490,8 @@ func PropertySlice(vals ds.PropertySlice) SerializedPslice {
if v.IndexSetting() == ds.NoIndex {
continue
}
- data := ToBytes(v.ForIndex())
+
+ data := ToBytes(v)
dataS := string(data)
if !dups.Add(dataS) {
continue
@@ -504,35 +529,29 @@ func PropertyMapPartially(k *ds.Key, pm ds.PropertyMap) (ret SerializedPmap) {
}
func toBytesErr(i interface{}, ctx KeyContext) (ret []byte, err error) {
- buf := &bytes.Buffer{}
- switch x := i.(type) {
- case ds.GeoPoint:
- err = WriteGeoPoint(buf, x)
+ buf := bytes.Buffer{}
+ switch t := i.(type) {
case ds.IndexColumn:
- err = WriteIndexColumn(buf, x)
+ err = WriteIndexColumn(&buf, t)
case ds.IndexDefinition:
- err = WriteIndexDefinition(buf, x)
-
- case *ds.Key:
- err = WriteKey(buf, ctx, x)
+ err = WriteIndexDefinition(&buf, t)
case ds.KeyTok:
- err = WriteKeyTok(buf, x)
+ err = WriteKeyTok(&buf, t)
case ds.Property:
- err = WriteProperty(buf, ctx, x)
+ err = WriteIndexProperty(&buf, ctx, t)
case ds.PropertyMap:
- err = WritePropertyMap(buf, ctx, x)
-
- case time.Time:
- err = WriteTime(buf, x)
+ err = WritePropertyMap(&buf, ctx, t)
default:
- err = fmt.Errorf("unknown type for ToBytes: %T", i)
+ _, v := ds.MkProperty(i).IndexTypeAndValue()
+ err = writeIndexValue(&buf, ctx, v)
}
+
if err == nil {
ret = buf.Bytes()
}
« no previous file with comments | « service/datastore/properties_test.go ('k') | service/datastore/serialize/serialize_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698