| 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 17 matching lines...) Expand all Loading... |
| 28 convert bool | 28 convert bool |
| 29 metaVal interface{} | 29 metaVal interface{} |
| 30 canSet bool | 30 canSet bool |
| 31 } | 31 } |
| 32 | 32 |
| 33 type structCodec struct { | 33 type structCodec struct { |
| 34 byMeta map[string]int | 34 byMeta map[string]int |
| 35 byName map[string]int | 35 byName map[string]int |
| 36 byIndex []structTag | 36 byIndex []structTag |
| 37 hasSlice bool | 37 hasSlice bool |
| 38 mgs bool |
| 38 problem error | 39 problem error |
| 39 } | 40 } |
| 40 | 41 |
| 41 type structPLS struct { | 42 type structPLS struct { |
| 42 o reflect.Value | 43 o reflect.Value |
| 43 c *structCodec | 44 c *structCodec |
| 44 } | 45 } |
| 45 | 46 |
| 47 func (p *structPLS) getMGS() MetaGetterSetter { |
| 48 if !p.c.mgs { |
| 49 return nil |
| 50 } |
| 51 return p.o.Addr().Interface().(MetaGetterSetter) |
| 52 } |
| 53 |
| 46 var _ PropertyLoadSaver = (*structPLS)(nil) | 54 var _ PropertyLoadSaver = (*structPLS)(nil) |
| 47 | 55 |
| 48 // typeMismatchReason returns a string explaining why the property p could not | 56 // typeMismatchReason returns a string explaining why the property p could not |
| 49 // be stored in an entity field of type v.Type(). | 57 // be stored in an entity field of type v.Type(). |
| 50 func typeMismatchReason(val interface{}, v reflect.Value) string { | 58 func typeMismatchReason(val interface{}, v reflect.Value) string { |
| 51 entityType := reflect.TypeOf(val) | 59 entityType := reflect.TypeOf(val) |
| 52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) | 60 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) |
| 53 } | 61 } |
| 54 | 62 |
| 55 func (p *structPLS) Load(propMap PropertyMap) error { | 63 func (p *structPLS) Load(propMap PropertyMap) error { |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 } | 290 } |
| 283 } | 291 } |
| 284 } | 292 } |
| 285 return | 293 return |
| 286 } | 294 } |
| 287 | 295 |
| 288 func (p *structPLS) GetMeta(key string) (interface{}, error) { | 296 func (p *structPLS) GetMeta(key string) (interface{}, error) { |
| 289 if err := p.Problem(); err != nil { | 297 if err := p.Problem(); err != nil { |
| 290 return nil, err | 298 return nil, err |
| 291 } | 299 } |
| 292 » idx, ok := p.c.byMeta[key] | 300 |
| 293 » if !ok { | 301 » if idx, ok := p.c.byMeta[key]; ok { |
| 294 » » if key == "kind" { | 302 » » return p.getMetaFor(idx), nil |
| 295 » » » return p.getDefaultKind(), nil | 303 » } |
| 304 |
| 305 » if p.c.mgs { |
| 306 » » ret, err := p.getMGS().GetMeta(key) |
| 307 » » if err == nil { |
| 308 » » » return ret, err |
| 309 » » } else if err != ErrMetaFieldUnset { |
| 310 » » » return nil, err |
| 296 } | 311 } |
| 297 return nil, ErrMetaFieldUnset | |
| 298 } | 312 } |
| 299 » return p.getMetaFor(idx), nil | 313 » if key == "kind" { |
| 314 » » return p.getDefaultKind(), nil |
| 315 » } |
| 316 » return nil, ErrMetaFieldUnset |
| 300 } | 317 } |
| 301 | 318 |
| 302 func (p *structPLS) getMetaFor(idx int) interface{} { | 319 func (p *structPLS) getMetaFor(idx int) interface{} { |
| 303 st := p.c.byIndex[idx] | 320 st := p.c.byIndex[idx] |
| 304 val := st.metaVal | 321 val := st.metaVal |
| 305 f := p.o.Field(idx) | 322 f := p.o.Field(idx) |
| 306 if st.canSet { | 323 if st.canSet { |
| 307 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte
rface()) { | 324 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte
rface()) { |
| 308 val = f.Interface() | 325 val = f.Interface() |
| 309 if bf, ok := val.(Toggle); ok { | 326 if bf, ok := val.(Toggle); ok { |
| 310 val = bf == On // true if On, otherwise false | 327 val = bf == On // true if On, otherwise false |
| 311 } | 328 } |
| 312 } | 329 } |
| 313 } | 330 } |
| 314 return val | 331 return val |
| 315 } | 332 } |
| 316 | 333 |
| 317 func (p *structPLS) GetAllMeta() PropertyMap { | 334 func (p *structPLS) GetAllMeta() PropertyMap { |
| 318 » ret := make(PropertyMap, len(p.c.byMeta)+1) | 335 » ret := PropertyMap(nil) |
| 336 » needKind := true |
| 337 » if p.c.mgs { |
| 338 » » ret = p.getMGS().GetAllMeta() |
| 339 » » _, haveKind := ret["$kind"] |
| 340 » » needKind = !haveKind |
| 341 » } else { |
| 342 » » ret = make(PropertyMap, len(p.c.byMeta)+1) |
| 343 » } |
| 319 for k, idx := range p.c.byMeta { | 344 for k, idx := range p.c.byMeta { |
| 320 val := p.getMetaFor(idx) | 345 val := p.getMetaFor(idx) |
| 321 p := Property{} | 346 p := Property{} |
| 322 if err := p.SetValue(val, NoIndex); err != nil { | 347 if err := p.SetValue(val, NoIndex); err != nil { |
| 323 continue | 348 continue |
| 324 } | 349 } |
| 325 ret["$"+k] = []Property{p} | 350 ret["$"+k] = []Property{p} |
| 326 } | 351 } |
| 327 » if _, ok := p.c.byMeta["kind"]; !ok { | 352 » if needKind { |
| 328 » » ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind())} | 353 » » if _, ok := p.c.byMeta["kind"]; !ok { |
| 354 » » » ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} |
| 355 » » } |
| 329 } | 356 } |
| 330 return ret | 357 return ret |
| 331 } | 358 } |
| 332 | 359 |
| 333 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { | 360 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { |
| 334 return GetMetaDefaultImpl(p.GetMeta, key, def) | 361 return GetMetaDefaultImpl(p.GetMeta, key, def) |
| 335 } | 362 } |
| 336 | 363 |
| 337 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { | 364 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { |
| 338 if err = p.Problem(); err != nil { | 365 if err = p.Problem(); err != nil { |
| 339 return | 366 return |
| 340 } | 367 } |
| 341 idx, ok := p.c.byMeta[key] | 368 idx, ok := p.c.byMeta[key] |
| 342 if !ok { | 369 if !ok { |
| 370 if p.c.mgs { |
| 371 return p.getMGS().SetMeta(key, val) |
| 372 } |
| 343 return ErrMetaFieldUnset | 373 return ErrMetaFieldUnset |
| 344 } | 374 } |
| 345 if !p.c.byIndex[idx].canSet { | 375 if !p.c.byIndex[idx].canSet { |
| 346 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi
eld", key) | 376 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi
eld", key) |
| 347 } | 377 } |
| 348 // setting a BoolField | 378 // setting a BoolField |
| 349 if b, ok := val.(bool); ok { | 379 if b, ok := val.(bool); ok { |
| 350 if b { | 380 if b { |
| 351 val = On | 381 val = On |
| 352 } else { | 382 } else { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 | 441 |
| 412 me := func(fmtStr string, args ...interface{}) error { | 442 me := func(fmtStr string, args ...interface{}) error { |
| 413 return fmt.Errorf(fmtStr, args...) | 443 return fmt.Errorf(fmtStr, args...) |
| 414 } | 444 } |
| 415 | 445 |
| 416 c = &structCodec{ | 446 c = &structCodec{ |
| 417 byIndex: make([]structTag, t.NumField()), | 447 byIndex: make([]structTag, t.NumField()), |
| 418 byName: make(map[string]int, t.NumField()), | 448 byName: make(map[string]int, t.NumField()), |
| 419 byMeta: make(map[string]int, t.NumField()), | 449 byMeta: make(map[string]int, t.NumField()), |
| 420 problem: errRecursiveStruct, // we'll clear this later if it's n
ot recursive | 450 problem: errRecursiveStruct, // we'll clear this later if it's n
ot recursive |
| 451 mgs: reflect.PtrTo(t).Implements(typeOfMGS), |
| 421 } | 452 } |
| 422 defer func() { | 453 defer func() { |
| 423 // If the codec has a problem, free up the indexes | 454 // If the codec has a problem, free up the indexes |
| 424 if c.problem != nil { | 455 if c.problem != nil { |
| 425 c.byIndex = nil | 456 c.byIndex = nil |
| 426 c.byName = nil | 457 c.byName = nil |
| 427 c.byMeta = nil | 458 c.byMeta = nil |
| 428 } | 459 } |
| 429 }() | 460 }() |
| 430 structCodecs[t] = c | 461 structCodecs[t] = c |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 switch val { | 604 switch val { |
| 574 case "on", "On", "true": | 605 case "on", "On", "true": |
| 575 return true, nil | 606 return true, nil |
| 576 case "off", "Off", "false": | 607 case "off", "Off", "false": |
| 577 return false, nil | 608 return false, nil |
| 578 } | 609 } |
| 579 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) |
| 580 } | 611 } |
| 581 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) |
| 582 } | 613 } |
| OLD | NEW |