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 { | |
dnj
2015/11/03 01:18:10
nit: Handle err != nil (more standard).
| |
318 return prop.value, err | |
319 } | |
320 return nil, 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) |
dnj
2015/11/03 01:18:10
Do we care about non-nil errors? If not, have getM
iannucci
2015/11/03 01:29:12
eh, returning an error is standarder
dnj
2015/11/03 03:11:25
Gah I I don't like the feel of returning an error
iannucci
2015/11/03 20:29:32
done
| |
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 if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { | |
dnj
2015/11/03 01:18:10
nit: st.convert = reflect.PtrTo(ft)....
iannucci
2015/11/03 01:29:12
DERP
| |
471 st.convert = true | |
472 } | |
452 switch { | 473 switch { |
453 case name == "": | 474 case name == "": |
454 if !f.Anonymous { | 475 if !f.Anonymous { |
455 name = f.Name | 476 name = f.Name |
456 } | 477 } |
457 case name[0] == '$': | 478 case name[0] == '$': |
458 name = name[1:] | 479 name = name[1:] |
459 if _, ok := c.byMeta[name]; ok { | 480 if _, ok := c.byMeta[name]; ok { |
460 c.problem = me("meta field %q set multiple times ", "$"+name) | 481 c.problem = me("meta field %q set multiple times ", "$"+name) |
461 return | 482 return |
462 } | 483 } |
463 c.byMeta[name] = i | 484 c.byMeta[name] = i |
464 » » » mv, err := convertMeta(opts, f.Type) | 485 » » » if !st.convert { |
465 » » » if err != nil { | 486 » » » » mv, err := convertMeta(opts, f.Type) |
dnj
2015/11/03 01:18:10
nit: f.Type => ft
iannucci
2015/11/03 01:29:13
done (and others)
| |
466 » » » » c.problem = me("meta field %q has bad type: %s", "$"+name, err) | 487 » » » » if err != nil { |
467 » » » » return | 488 » » » » » c.problem = me("meta field %q has bad ty pe: %s", "$"+name, err) |
489 » » » » » return | |
490 » » » » } | |
491 » » » » st.metaVal = mv | |
468 } | 492 } |
469 st.metaVal = mv | |
470 fallthrough | 493 fallthrough |
471 case name == "-": | 494 case name == "-": |
472 st.name = "-" | 495 st.name = "-" |
473 continue | 496 continue |
474 default: | 497 default: |
475 if !validPropertyName(name) { | 498 if !validPropertyName(name) { |
476 c.problem = me("struct tag has invalid property name: %q", name) | 499 c.problem = me("struct tag has invalid property name: %q", name) |
477 return | 500 return |
478 } | 501 } |
479 } | 502 } |
480 if !st.canSet { | 503 if !st.canSet { |
481 st.name = "-" | 504 st.name = "-" |
482 continue | 505 continue |
483 } | 506 } |
484 | 507 |
485 substructType := reflect.Type(nil) | 508 substructType := reflect.Type(nil) |
486 » » ft := f.Type | 509 » » if !st.convert { |
487 » » if reflect.PtrTo(ft).Implements(typeOfPropertyConverter) { | |
488 » » » st.convert = true | |
489 » » } else { | |
490 switch f.Type.Kind() { | 510 switch f.Type.Kind() { |
491 case reflect.Struct: | 511 case reflect.Struct: |
492 if ft != typeOfTime && ft != typeOfGeoPoint { | 512 if ft != typeOfTime && ft != typeOfGeoPoint { |
493 substructType = ft | 513 substructType = ft |
494 } | 514 } |
495 case reflect.Slice: | 515 case reflect.Slice: |
496 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro pertyConverter) { | 516 if reflect.PtrTo(ft.Elem()).Implements(typeOfPro pertyConverter) { |
497 st.convert = true | 517 st.convert = true |
498 } else if ft.Elem().Kind() == reflect.Struct { | 518 } else if ft.Elem().Kind() == reflect.Struct { |
499 substructType = ft.Elem() | 519 substructType = ft.Elem() |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
584 switch val { | 604 switch val { |
585 case "on", "On", "true": | 605 case "on", "On", "true": |
586 return true, nil | 606 return true, nil |
587 case "off", "Off", "false": | 607 case "off", "Off", "false": |
588 return false, nil | 608 return false, nil |
589 } | 609 } |
590 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) | 610 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) |
591 } | 611 } |
592 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) | 612 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) |
593 } | 613 } |
OLD | NEW |