| 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 |