OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package serialize | 5 package serialize |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "errors" | 9 "errors" |
10 "fmt" | 10 "fmt" |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 } | 210 } |
211 return time.Unix(int64(v/1e6), int64((v%1e6)*1e3)).UTC(), nil | 211 return time.Unix(int64(v/1e6), int64((v%1e6)*1e3)).UTC(), nil |
212 } | 212 } |
213 | 213 |
214 // WriteProperty writes a Property to the buffer. `context` behaves the same | 214 // WriteProperty writes a Property to the buffer. `context` behaves the same |
215 // way that it does for WriteKey, but only has an effect if `p` contains a | 215 // way that it does for WriteKey, but only has an effect if `p` contains a |
216 // Key as its Value. | 216 // Key as its Value. |
217 func WriteProperty(buf Buffer, context KeyContext, p ds.Property) (err error) { | 217 func WriteProperty(buf Buffer, context KeyContext, p ds.Property) (err error) { |
218 defer recoverTo(&err) | 218 defer recoverTo(&err) |
219 typb := byte(p.Type()) | 219 typb := byte(p.Type()) |
220 » if p.IndexSetting() == ds.NoIndex { | 220 » if p.IndexSetting() != ds.NoIndex { |
221 typb |= 0x80 | 221 typb |= 0x80 |
222 } | 222 } |
223 panicIf(buf.WriteByte(typb)) | 223 panicIf(buf.WriteByte(typb)) |
224 switch p.Type() { | 224 switch p.Type() { |
225 case ds.PTNull, ds.PTBoolTrue, ds.PTBoolFalse: | 225 case ds.PTNull, ds.PTBoolTrue, ds.PTBoolFalse: |
226 case ds.PTInt: | 226 case ds.PTInt: |
227 _, err = cmpbin.WriteInt(buf, p.Value().(int64)) | 227 _, err = cmpbin.WriteInt(buf, p.Value().(int64)) |
228 case ds.PTFloat: | 228 case ds.PTFloat: |
229 _, err = cmpbin.WriteFloat64(buf, p.Value().(float64)) | 229 _, err = cmpbin.WriteFloat64(buf, p.Value().(float64)) |
230 case ds.PTString: | 230 case ds.PTString: |
(...skipping 19 matching lines...) Expand all Loading... |
250 // ReadProperty reads a Property from the buffer. `context`, `appid`, and | 250 // ReadProperty reads a Property from the buffer. `context`, `appid`, and |
251 // `namespace` behave the same way they do for ReadKey, but only have an | 251 // `namespace` behave the same way they do for ReadKey, but only have an |
252 // effect if the decoded property has a Key value. | 252 // effect if the decoded property has a Key value. |
253 func ReadProperty(buf Buffer, context KeyContext, appid, namespace string) (p ds
.Property, err error) { | 253 func ReadProperty(buf Buffer, context KeyContext, appid, namespace string) (p ds
.Property, err error) { |
254 val := interface{}(nil) | 254 val := interface{}(nil) |
255 typb, err := buf.ReadByte() | 255 typb, err := buf.ReadByte() |
256 if err != nil { | 256 if err != nil { |
257 return | 257 return |
258 } | 258 } |
259 is := ds.ShouldIndex | 259 is := ds.ShouldIndex |
260 » if (typb & 0x80) != 0 { | 260 » if (typb & 0x80) == 0 { |
261 is = ds.NoIndex | 261 is = ds.NoIndex |
262 } | 262 } |
263 switch ds.PropertyType(typb & 0x7f) { | 263 switch ds.PropertyType(typb & 0x7f) { |
264 case ds.PTNull: | 264 case ds.PTNull: |
265 case ds.PTBoolTrue: | 265 case ds.PTBoolTrue: |
266 val = true | 266 val = true |
267 case ds.PTBoolFalse: | 267 case ds.PTBoolFalse: |
268 val = false | 268 val = false |
269 case ds.PTInt: | 269 case ds.PTInt: |
270 val, _, err = cmpbin.ReadInt(buf) | 270 val, _, err = cmpbin.ReadInt(buf) |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 c.Direction = ds.DESCENDING | 404 c.Direction = ds.DESCENDING |
405 } | 405 } |
406 c.Property, _, err = cmpbin.ReadString(buf) | 406 c.Property, _, err = cmpbin.ReadString(buf) |
407 return | 407 return |
408 } | 408 } |
409 | 409 |
410 // WriteIndexDefinition writes an IndexDefinition to the buffer | 410 // WriteIndexDefinition writes an IndexDefinition to the buffer |
411 func WriteIndexDefinition(buf Buffer, i ds.IndexDefinition) (err error) { | 411 func WriteIndexDefinition(buf Buffer, i ds.IndexDefinition) (err error) { |
412 defer recoverTo(&err) | 412 defer recoverTo(&err) |
413 | 413 |
414 if i.Builtin() { | |
415 panicIf(buf.WriteByte(0)) | |
416 } else { | |
417 panicIf(buf.WriteByte(1)) | |
418 } | |
419 _, err = cmpbin.WriteString(buf, i.Kind) | 414 _, err = cmpbin.WriteString(buf, i.Kind) |
420 panicIf(err) | 415 panicIf(err) |
421 if !i.Ancestor { | 416 if !i.Ancestor { |
422 panicIf(buf.WriteByte(0)) | 417 panicIf(buf.WriteByte(0)) |
423 } else { | 418 } else { |
424 panicIf(buf.WriteByte(1)) | 419 panicIf(buf.WriteByte(1)) |
425 } | 420 } |
426 _, err = cmpbin.WriteUint(buf, uint64(len(i.SortBy))) | |
427 panicIf(err) | |
428 for _, sb := range i.SortBy { | 421 for _, sb := range i.SortBy { |
| 422 panicIf(buf.WriteByte(1)) |
429 panicIf(WriteIndexColumn(buf, sb)) | 423 panicIf(WriteIndexColumn(buf, sb)) |
430 } | 424 } |
431 » return | 425 » return buf.WriteByte(0) |
432 } | 426 } |
433 | 427 |
434 // ReadIndexDefinition reads an IndexDefinition from the buffer. | 428 // ReadIndexDefinition reads an IndexDefinition from the buffer. |
435 func ReadIndexDefinition(buf Buffer) (i ds.IndexDefinition, err error) { | 429 func ReadIndexDefinition(buf Buffer) (i ds.IndexDefinition, err error) { |
436 defer recoverTo(&err) | 430 defer recoverTo(&err) |
437 | 431 |
438 // discard builtin/complex byte | |
439 _, err = buf.ReadByte() | |
440 panicIf(err) | |
441 | |
442 i.Kind, _, err = cmpbin.ReadString(buf) | 432 i.Kind, _, err = cmpbin.ReadString(buf) |
443 panicIf(err) | 433 panicIf(err) |
444 | 434 |
445 anc, err := buf.ReadByte() | 435 anc, err := buf.ReadByte() |
446 panicIf(err) | 436 panicIf(err) |
447 | 437 |
448 i.Ancestor = anc == 1 | 438 i.Ancestor = anc == 1 |
449 | 439 |
450 » numSorts, _, err := cmpbin.ReadUint(buf) | 440 » for { |
451 » panicIf(err) | 441 » » ctrl := byte(0) |
| 442 » » ctrl, err = buf.ReadByte() |
| 443 » » panicIf(err) |
| 444 » » if ctrl == 0 { |
| 445 » » » break |
| 446 » » } |
| 447 » » if len(i.SortBy) > MaxIndexColumns { |
| 448 » » » err = fmt.Errorf("datastore: Got over %d sort orders", M
axIndexColumns) |
| 449 » » » return |
| 450 » » } |
452 | 451 |
453 » if numSorts > MaxIndexColumns { | 452 » » sb, err := ReadIndexColumn(buf) |
454 » » err = fmt.Errorf("datastore: Got over %d sort orders: %d", | 453 » » panicIf(err) |
455 » » » MaxIndexColumns, numSorts) | |
456 » » return | |
457 » } | |
458 | 454 |
459 » if numSorts > 0 { | 455 » » i.SortBy = append(i.SortBy, sb) |
460 » » i.SortBy = make([]ds.IndexColumn, numSorts) | |
461 » » for idx := range i.SortBy { | |
462 » » » i.SortBy[idx], err = ReadIndexColumn(buf) | |
463 » » » panicIf(err) | |
464 » » } | |
465 } | 456 } |
466 | 457 |
467 return | 458 return |
468 } | 459 } |
469 | 460 |
470 func toBytesErr(i interface{}, ctx KeyContext) (ret []byte, err error) { | 461 func toBytesErr(i interface{}, ctx KeyContext) (ret []byte, err error) { |
471 buf := &bytes.Buffer{} | 462 buf := &bytes.Buffer{} |
472 switch x := i.(type) { | 463 switch x := i.(type) { |
473 case ds.GeoPoint: | 464 case ds.GeoPoint: |
474 err = WriteGeoPoint(buf, x) | 465 err = WriteGeoPoint(buf, x) |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 } | 548 } |
558 } | 549 } |
559 | 550 |
560 func recoverTo(err *error) { | 551 func recoverTo(err *error) { |
561 if r := recover(); r != nil { | 552 if r := recover(); r != nil { |
562 if rerr := r.(parseError); rerr != nil { | 553 if rerr := r.(parseError); rerr != nil { |
563 *err = error(rerr) | 554 *err = error(rerr) |
564 } | 555 } |
565 } | 556 } |
566 } | 557 } |
OLD | NEW |