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 { | |
Vadim Sh.
2015/10/13 04:27:48
:) https://goo.gl/ik3wWF
iannucci
2015/10/13 04:34:40
:)
| |
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 |