| 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 | |
| 39 problem error | 38 problem error |
| 40 } | 39 } |
| 41 | 40 |
| 42 type structPLS struct { | 41 type structPLS struct { |
| 43 o reflect.Value | 42 o reflect.Value |
| 44 c *structCodec | 43 c *structCodec |
| 45 } | 44 } |
| 46 | 45 |
| 47 func (p *structPLS) getMGS() MetaGetterSetter { | |
| 48 if !p.c.mgs { | |
| 49 return nil | |
| 50 } | |
| 51 return p.o.Addr().Interface().(MetaGetterSetter) | |
| 52 } | |
| 53 | |
| 54 var _ PropertyLoadSaver = (*structPLS)(nil) | 46 var _ PropertyLoadSaver = (*structPLS)(nil) |
| 55 | 47 |
| 56 // typeMismatchReason returns a string explaining why the property p could not | 48 // typeMismatchReason returns a string explaining why the property p could not |
| 57 // be stored in an entity field of type v.Type(). | 49 // be stored in an entity field of type v.Type(). |
| 58 func typeMismatchReason(val interface{}, v reflect.Value) string { | 50 func typeMismatchReason(val interface{}, v reflect.Value) string { |
| 59 entityType := reflect.TypeOf(val) | 51 entityType := reflect.TypeOf(val) |
| 60 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) | 52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) |
| 61 } | 53 } |
| 62 | 54 |
| 63 func (p *structPLS) Load(propMap PropertyMap) error { | 55 func (p *structPLS) Load(propMap PropertyMap) error { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 } else { | 211 } else { |
| 220 ret = make(PropertyMap, len(p.c.byName)) | 212 ret = make(PropertyMap, len(p.c.byName)) |
| 221 } | 213 } |
| 222 if _, err := p.save(ret, "", ShouldIndex); err != nil { | 214 if _, err := p.save(ret, "", ShouldIndex); err != nil { |
| 223 return nil, err | 215 return nil, err |
| 224 } | 216 } |
| 225 return ret, nil | 217 return ret, nil |
| 226 } | 218 } |
| 227 | 219 |
| 228 func (p *structPLS) getDefaultKind() string { | 220 func (p *structPLS) getDefaultKind() string { |
| 221 if !p.o.IsValid() { |
| 222 return "" |
| 223 } |
| 229 return p.o.Type().Name() | 224 return p.o.Type().Name() |
| 230 } | 225 } |
| 231 | 226 |
| 232 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i
dxCount int, err error) { | 227 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i
dxCount int, err error) { |
| 233 if err = p.Problem(); err != nil { | 228 if err = p.Problem(); err != nil { |
| 234 return | 229 return |
| 235 } | 230 } |
| 236 | 231 |
| 237 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru
ctTag) (err error) { | 232 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru
ctTag) (err error) { |
| 238 if st.substructCodec != nil { | 233 if st.substructCodec != nil { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 | 290 |
| 296 func (p *structPLS) GetMeta(key string) (interface{}, error) { | 291 func (p *structPLS) GetMeta(key string) (interface{}, error) { |
| 297 if err := p.Problem(); err != nil { | 292 if err := p.Problem(); err != nil { |
| 298 return nil, err | 293 return nil, err |
| 299 } | 294 } |
| 300 | 295 |
| 301 if idx, ok := p.c.byMeta[key]; ok { | 296 if idx, ok := p.c.byMeta[key]; ok { |
| 302 return p.getMetaFor(idx), nil | 297 return p.getMetaFor(idx), nil |
| 303 } | 298 } |
| 304 | 299 |
| 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 | |
| 311 } | |
| 312 } | |
| 313 if key == "kind" { | 300 if key == "kind" { |
| 314 return p.getDefaultKind(), nil | 301 return p.getDefaultKind(), nil |
| 315 } | 302 } |
| 316 return nil, ErrMetaFieldUnset | 303 return nil, ErrMetaFieldUnset |
| 317 } | 304 } |
| 318 | 305 |
| 319 func (p *structPLS) getMetaFor(idx int) interface{} { | 306 func (p *structPLS) getMetaFor(idx int) interface{} { |
| 320 st := p.c.byIndex[idx] | 307 st := p.c.byIndex[idx] |
| 321 val := st.metaVal | 308 val := st.metaVal |
| 322 f := p.o.Field(idx) | 309 f := p.o.Field(idx) |
| 323 if st.canSet { | 310 if st.canSet { |
| 324 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte
rface()) { | 311 if !reflect.DeepEqual(reflect.Zero(f.Type()).Interface(), f.Inte
rface()) { |
| 325 val = f.Interface() | 312 val = f.Interface() |
| 326 if bf, ok := val.(Toggle); ok { | 313 if bf, ok := val.(Toggle); ok { |
| 327 val = bf == On // true if On, otherwise false | 314 val = bf == On // true if On, otherwise false |
| 328 } | 315 } |
| 329 } | 316 } |
| 330 } | 317 } |
| 331 return val | 318 return val |
| 332 } | 319 } |
| 333 | 320 |
| 334 func (p *structPLS) GetAllMeta() PropertyMap { | 321 func (p *structPLS) GetAllMeta() PropertyMap { |
| 335 ret := PropertyMap(nil) | |
| 336 needKind := true | 322 needKind := true |
| 337 » if p.c.mgs { | 323 » ret := make(PropertyMap, len(p.c.byMeta)+1) |
| 338 » » ret = p.getMGS().GetAllMeta() | |
| 339 » » _, haveKind := ret["$kind"] | |
| 340 » » needKind = !haveKind | |
| 341 » } else { | |
| 342 » » ret = make(PropertyMap, len(p.c.byMeta)+1) | |
| 343 » } | |
| 344 for k, idx := range p.c.byMeta { | 324 for k, idx := range p.c.byMeta { |
| 345 val := p.getMetaFor(idx) | 325 val := p.getMetaFor(idx) |
| 346 p := Property{} | 326 p := Property{} |
| 347 if err := p.SetValue(val, NoIndex); err != nil { | 327 if err := p.SetValue(val, NoIndex); err != nil { |
| 348 continue | 328 continue |
| 349 } | 329 } |
| 350 ret["$"+k] = []Property{p} | 330 ret["$"+k] = []Property{p} |
| 351 } | 331 } |
| 352 if needKind { | 332 if needKind { |
| 353 if _, ok := p.c.byMeta["kind"]; !ok { | 333 if _, ok := p.c.byMeta["kind"]; !ok { |
| 354 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} | 334 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} |
| 355 } | 335 } |
| 356 } | 336 } |
| 357 return ret | 337 return ret |
| 358 } | 338 } |
| 359 | 339 |
| 360 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { | 340 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { |
| 361 return GetMetaDefaultImpl(p.GetMeta, key, def) | 341 return GetMetaDefaultImpl(p.GetMeta, key, def) |
| 362 } | 342 } |
| 363 | 343 |
| 364 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { | 344 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { |
| 365 if err = p.Problem(); err != nil { | 345 if err = p.Problem(); err != nil { |
| 366 return | 346 return |
| 367 } | 347 } |
| 368 idx, ok := p.c.byMeta[key] | 348 idx, ok := p.c.byMeta[key] |
| 369 if !ok { | 349 if !ok { |
| 370 if p.c.mgs { | |
| 371 return p.getMGS().SetMeta(key, val) | |
| 372 } | |
| 373 return ErrMetaFieldUnset | 350 return ErrMetaFieldUnset |
| 374 } | 351 } |
| 375 if !p.c.byIndex[idx].canSet { | 352 if !p.c.byIndex[idx].canSet { |
| 376 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi
eld", key) | 353 return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi
eld", key) |
| 377 } | 354 } |
| 378 // setting a BoolField | 355 // setting a BoolField |
| 379 if b, ok := val.(bool); ok { | 356 if b, ok := val.(bool); ok { |
| 380 if b { | 357 if b { |
| 381 val = On | 358 val = On |
| 382 } else { | 359 } else { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 | 418 |
| 442 me := func(fmtStr string, args ...interface{}) error { | 419 me := func(fmtStr string, args ...interface{}) error { |
| 443 return fmt.Errorf(fmtStr, args...) | 420 return fmt.Errorf(fmtStr, args...) |
| 444 } | 421 } |
| 445 | 422 |
| 446 c = &structCodec{ | 423 c = &structCodec{ |
| 447 byIndex: make([]structTag, t.NumField()), | 424 byIndex: make([]structTag, t.NumField()), |
| 448 byName: make(map[string]int, t.NumField()), | 425 byName: make(map[string]int, t.NumField()), |
| 449 byMeta: make(map[string]int, t.NumField()), | 426 byMeta: make(map[string]int, t.NumField()), |
| 450 problem: errRecursiveStruct, // we'll clear this later if it's n
ot recursive | 427 problem: errRecursiveStruct, // we'll clear this later if it's n
ot recursive |
| 451 mgs: reflect.PtrTo(t).Implements(typeOfMGS), | |
| 452 } | 428 } |
| 453 defer func() { | 429 defer func() { |
| 454 // If the codec has a problem, free up the indexes | 430 // If the codec has a problem, free up the indexes |
| 455 if c.problem != nil { | 431 if c.problem != nil { |
| 456 c.byIndex = nil | 432 c.byIndex = nil |
| 457 c.byName = nil | 433 c.byName = nil |
| 458 c.byMeta = nil | 434 c.byMeta = nil |
| 459 } | 435 } |
| 460 }() | 436 }() |
| 461 structCodecs[t] = c | 437 structCodecs[t] = c |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 switch val { | 580 switch val { |
| 605 case "on", "On", "true": | 581 case "on", "On", "true": |
| 606 return true, nil | 582 return true, nil |
| 607 case "off", "Off", "false": | 583 case "off", "Off", "false": |
| 608 return false, nil | 584 return false, nil |
| 609 } | 585 } |
| 610 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) | 586 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) |
| 611 } | 587 } |
| 612 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) | 588 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) |
| 613 } | 589 } |
| OLD | NEW |