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 // HEAVILY adapted from github.com/golang/appengine/datastore | 5 // HEAVILY adapted from github.com/golang/appengine/datastore |
6 | 6 |
7 package datastore | 7 package datastore |
8 | 8 |
9 import ( | 9 import ( |
10 "fmt" | 10 "fmt" |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 } | 291 } |
292 return | 292 return |
293 } | 293 } |
294 | 294 |
295 func (p *structPLS) GetMeta(key string) (interface{}, error) { | 295 func (p *structPLS) GetMeta(key string) (interface{}, error) { |
296 if err := p.Problem(); err != nil { | 296 if err := p.Problem(); err != nil { |
297 return nil, err | 297 return nil, err |
298 } | 298 } |
299 | 299 |
300 if idx, ok := p.c.byMeta[key]; ok { | 300 if idx, ok := p.c.byMeta[key]; ok { |
301 » » return p.getMetaFor(idx), nil | 301 » » return p.getMetaFor(idx) |
302 } | 302 } |
303 | 303 |
304 if key == "kind" { | 304 if key == "kind" { |
305 return p.getDefaultKind(), nil | 305 return p.getDefaultKind(), nil |
306 } | 306 } |
307 return nil, ErrMetaFieldUnset | 307 return nil, ErrMetaFieldUnset |
308 } | 308 } |
309 | 309 |
310 func (p *structPLS) getMetaFor(idx int) interface{} { | 310 func (p *structPLS) getMetaFor(idx int) (interface{}, error) { |
311 st := p.c.byIndex[idx] | 311 st := p.c.byIndex[idx] |
312 val := st.metaVal | 312 val := st.metaVal |
313 f := p.o.Field(idx) | |
314 if st.canSet { | 313 if st.canSet { |
| 314 f := p.o.Field(idx) |
| 315 if st.convert { |
| 316 prop, err := f.Addr().Interface().(PropertyConverter).To
Property() |
| 317 if err != nil { |
| 318 return nil, err |
| 319 } |
| 320 return prop.value, err |
| 321 } |
| 322 |
315 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte
rface()) { | 323 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte
rface()) { |
316 val = f.Interface() | 324 val = f.Interface() |
317 if bf, ok := val.(Toggle); ok { | 325 if bf, ok := val.(Toggle); ok { |
318 val = bf == On // true if On, otherwise false | 326 val = bf == On // true if On, otherwise false |
319 } | 327 } |
320 } | 328 } |
321 } | 329 } |
322 » return val | 330 » return val, nil |
323 } | 331 } |
324 | 332 |
325 func (p *structPLS) GetAllMeta() PropertyMap { | 333 func (p *structPLS) GetAllMeta() PropertyMap { |
326 needKind := true | 334 needKind := true |
327 ret := make(PropertyMap, len(p.c.byMeta)+1) | 335 ret := make(PropertyMap, len(p.c.byMeta)+1) |
328 for k, idx := range p.c.byMeta { | 336 for k, idx := range p.c.byMeta { |
329 » » val := p.getMetaFor(idx) | 337 » » val, err := p.getMetaFor(idx) |
330 » » p := Property{} | 338 » » if err == nil { |
331 » » if err := p.SetValue(val, NoIndex); err != nil { | 339 » » » p := Property{} |
332 » » » continue | 340 » » » if err := p.SetValue(val, NoIndex); err != nil { |
| 341 » » » » continue |
| 342 » » » } |
| 343 » » » ret["$"+k] = []Property{p} |
333 } | 344 } |
334 ret["$"+k] = []Property{p} | |
335 } | 345 } |
336 if needKind { | 346 if needKind { |
337 if _, ok := p.c.byMeta["kind"]; !ok { | 347 if _, ok := p.c.byMeta["kind"]; !ok { |
338 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} | 348 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} |
339 } | 349 } |
340 } | 350 } |
341 return ret | 351 return ret |
342 } | 352 } |
343 | 353 |
344 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { | 354 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { |
345 return GetMetaDefaultImpl(p.GetMeta, key, def) | 355 return GetMetaDefaultImpl(p.GetMeta, key, def) |
346 } | 356 } |
347 | 357 |
348 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { | 358 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { |
349 if err = p.Problem(); err != nil { | 359 if err = p.Problem(); err != nil { |
350 return | 360 return |
351 } | 361 } |
352 idx, ok := p.c.byMeta[key] | 362 idx, ok := p.c.byMeta[key] |
353 if !ok { | 363 if !ok { |
354 return ErrMetaFieldUnset | 364 return ErrMetaFieldUnset |
355 } | 365 } |
356 » if !p.c.byIndex[idx].canSet { | 366 » st := p.c.byIndex[idx] |
| 367 » if !st.canSet { |
357 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi
eld", key) | 368 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi
eld", key) |
358 } | 369 } |
| 370 if st.convert { |
| 371 return p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro
mProperty( |
| 372 MkPropertyNI(val)) |
| 373 } |
| 374 |
359 // setting a BoolField | 375 // setting a BoolField |
360 if b, ok := val.(bool); ok { | 376 if b, ok := val.(bool); ok { |
361 if b { | 377 if b { |
362 val = On | 378 val = On |
363 } else { | 379 } else { |
364 val = Off | 380 val = Off |
365 } | 381 } |
366 } | 382 } |
367 f := p.o.Field(idx) | 383 f := p.o.Field(idx) |
368 if val == nil { | 384 if val == nil { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 c.byIndex = nil | 452 c.byIndex = nil |
437 c.byName = nil | 453 c.byName = nil |
438 c.byMeta = nil | 454 c.byMeta = nil |
439 } | 455 } |
440 }() | 456 }() |
441 structCodecs[t] = c | 457 structCodecs[t] = c |
442 | 458 |
443 for i := range c.byIndex { | 459 for i := range c.byIndex { |
444 st := &c.byIndex[i] | 460 st := &c.byIndex[i] |
445 f := t.Field(i) | 461 f := t.Field(i) |
| 462 ft := f.Type |
| 463 |
446 name := f.Tag.Get("gae") | 464 name := f.Tag.Get("gae") |
447 opts := "" | 465 opts := "" |
448 if i := strings.Index(name, ","); i != -1 { | 466 if i := strings.Index(name, ","); i != -1 { |
449 name, opts = name[:i], name[i+1:] | 467 name, opts = name[:i], name[i+1:] |
450 } | 468 } |
451 st.canSet = f.PkgPath == "" // blank == exported | 469 st.canSet = f.PkgPath == "" // blank == exported |
| 470 st.convert = reflect.PtrTo(ft).Implements(typeOfPropertyConverte
r) |
452 switch { | 471 switch { |
453 case name == "": | 472 case name == "": |
454 if !f.Anonymous { | 473 if !f.Anonymous { |
455 name = f.Name | 474 name = f.Name |
456 } | 475 } |
457 case name[0] == '$': | 476 case name[0] == '$': |
458 name = name[1:] | 477 name = name[1:] |
459 if _, ok := c.byMeta[name]; ok { | 478 if _, ok := c.byMeta[name]; ok { |
460 c.problem = me("meta field %q set multiple times
", "$"+name) | 479 c.problem = me("meta field %q set multiple times
", "$"+name) |
461 return | 480 return |
462 } | 481 } |
463 c.byMeta[name] = i | 482 c.byMeta[name] = i |
464 » » » mv, err := convertMeta(opts, f.Type) | 483 » » » if !st.convert { |
465 » » » if err != nil { | 484 » » » » mv, err := convertMeta(opts, ft) |
466 » » » » c.problem = me("meta field %q has bad type: %s",
"$"+name, err) | 485 » » » » if err != nil { |
467 » » » » return | 486 » » » » » c.problem = me("meta field %q has bad ty
pe: %s", "$"+name, err) |
| 487 » » » » » return |
| 488 » » » » } |
| 489 » » » » st.metaVal = mv |
468 } | 490 } |
469 st.metaVal = mv | |
470 fallthrough | 491 fallthrough |
471 case name == "-": | 492 case name == "-": |
472 st.name = "-" | 493 st.name = "-" |
473 continue | 494 continue |
474 default: | 495 default: |
475 if !validPropertyName(name) { | 496 if !validPropertyName(name) { |
476 c.problem = me("struct tag has invalid property
name: %q", name) | 497 c.problem = me("struct tag has invalid property
name: %q", name) |
477 return | 498 return |
478 } | 499 } |
479 } | 500 } |
480 if !st.canSet { | 501 if !st.canSet { |
481 st.name = "-" | 502 st.name = "-" |
482 continue | 503 continue |
483 } | 504 } |
484 | 505 |
485 substructType := reflect.Type(nil) | 506 substructType := reflect.Type(nil) |
486 » » ft := f.Type | 507 » » if !st.convert { |
487 » » if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { | 508 » » » switch ft.Kind() { |
488 » » » st.convert = true | |
489 » » } else { | |
490 » » » switch f.Type.Kind() { | |
491 case reflect.Struct: | 509 case reflect.Struct: |
492 if ft != typeOfTime && ft != typeOfGeoPoint { | 510 if ft != typeOfTime && ft != typeOfGeoPoint { |
493 substructType = ft | 511 substructType = ft |
494 } | 512 } |
495 case reflect.Slice: | 513 case reflect.Slice: |
496 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro
pertyConverter) { | 514 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro
pertyConverter) { |
497 st.convert = true | 515 st.convert = true |
498 } else if ft.Elem().Kind() == reflect.Struct { | 516 } else if ft.Elem().Kind() == reflect.Struct { |
499 substructType = ft.Elem() | 517 substructType = ft.Elem() |
500 } | 518 } |
501 st.isSlice = ft.Elem().Kind() != reflect.Uint8 | 519 st.isSlice = ft.Elem().Kind() != reflect.Uint8 |
502 c.hasSlice = c.hasSlice || st.isSlice | 520 c.hasSlice = c.hasSlice || st.isSlice |
503 case reflect.Interface: | 521 case reflect.Interface: |
504 c.problem = me("field %q has non-concrete interf
ace type %s", | 522 c.problem = me("field %q has non-concrete interf
ace type %s", |
505 » » » » » f.Name, f.Type) | 523 » » » » » f.Name, ft) |
506 return | 524 return |
507 } | 525 } |
508 } | 526 } |
509 | 527 |
510 if substructType != nil { | 528 if substructType != nil { |
511 sub := getStructCodecLocked(substructType) | 529 sub := getStructCodecLocked(substructType) |
512 if sub.problem != nil { | 530 if sub.problem != nil { |
513 if sub.problem == errRecursiveStruct { | 531 if sub.problem == errRecursiveStruct { |
514 c.problem = me("field %q is recursively
defined", f.Name) | 532 c.problem = me("field %q is recursively
defined", f.Name) |
515 } else { | 533 } else { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 switch val { | 602 switch val { |
585 case "on", "On", "true": | 603 case "on", "On", "true": |
586 return true, nil | 604 return true, nil |
587 case "off", "Off", "false": | 605 case "off", "Off", "false": |
588 return false, nil | 606 return false, nil |
589 } | 607 } |
590 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) | 608 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) |
591 } | 609 } |
592 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) | 610 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) |
593 } | 611 } |
OLD | NEW |