| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 var _ PropertyLoadSaver = (*structPLS)(nil) | 46 var _ PropertyLoadSaver = (*structPLS)(nil) |
| 47 | 47 |
| 48 // typeMismatchReason returns a string explaining why the property p could not | 48 // typeMismatchReason returns a string explaining why the property p could not |
| 49 // be stored in an entity field of type v.Type(). | 49 // be stored in an entity field of type v.Type(). |
| 50 func typeMismatchReason(val interface{}, v reflect.Value) string { | 50 func typeMismatchReason(val interface{}, v reflect.Value) string { |
| 51 entityType := reflect.TypeOf(val) | 51 entityType := reflect.TypeOf(val) |
| 52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) | 52 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type()) |
| 53 } | 53 } |
| 54 | 54 |
| 55 func (p *structPLS) Load(propMap PropertyMap) error { | 55 func (p *structPLS) Load(propMap PropertyMap) error { |
| 56 if err := p.Problem(); err != nil { | |
| 57 return err | |
| 58 } | |
| 59 | |
| 60 convFailures := errors.MultiError(nil) | 56 convFailures := errors.MultiError(nil) |
| 61 | 57 |
| 62 t := reflect.Type(nil) | 58 t := reflect.Type(nil) |
| 63 for name, props := range propMap { | 59 for name, props := range propMap { |
| 64 multiple := len(props) > 1 | 60 multiple := len(props) > 1 |
| 65 for i, prop := range props { | 61 for i, prop := range props { |
| 66 if reason := loadInner(p.c, p.o, i, name, prop, multiple
); reason != "" { | 62 if reason := loadInner(p.c, p.o, i, name, prop, multiple
); reason != "" { |
| 67 if t == nil { | 63 if t == nil { |
| 68 t = p.o.Type() | 64 t = p.o.Type() |
| 69 } | 65 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } | 194 } |
| 199 set(pVal) | 195 set(pVal) |
| 200 } | 196 } |
| 201 if slice.IsValid() { | 197 if slice.IsValid() { |
| 202 slice.Set(reflect.Append(slice, v)) | 198 slice.Set(reflect.Append(slice, v)) |
| 203 } | 199 } |
| 204 return "" | 200 return "" |
| 205 } | 201 } |
| 206 | 202 |
| 207 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) { | 203 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) { |
| 208 if err := p.Problem(); err != nil { | |
| 209 return nil, err | |
| 210 } | |
| 211 | |
| 212 ret := PropertyMap(nil) | 204 ret := PropertyMap(nil) |
| 213 if withMeta { | 205 if withMeta { |
| 214 ret = getMGS(p.o.Addr().Interface()).GetAllMeta() | 206 ret = getMGS(p.o.Addr().Interface()).GetAllMeta() |
| 215 } else { | 207 } else { |
| 216 ret = make(PropertyMap, len(p.c.byName)) | 208 ret = make(PropertyMap, len(p.c.byName)) |
| 217 } | 209 } |
| 218 if _, err := p.save(ret, "", ShouldIndex); err != nil { | 210 if _, err := p.save(ret, "", ShouldIndex); err != nil { |
| 219 return nil, err | 211 return nil, err |
| 220 } | 212 } |
| 221 return ret, nil | 213 return ret, nil |
| 222 } | 214 } |
| 223 | 215 |
| 224 func (p *structPLS) getDefaultKind() string { | 216 func (p *structPLS) getDefaultKind() string { |
| 225 if !p.o.IsValid() { | 217 if !p.o.IsValid() { |
| 226 return "" | 218 return "" |
| 227 } | 219 } |
| 228 return p.o.Type().Name() | 220 return p.o.Type().Name() |
| 229 } | 221 } |
| 230 | 222 |
| 231 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i
dxCount int, err error) { | 223 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i
dxCount int, err error) { |
| 232 if err = p.Problem(); err != nil { | |
| 233 return | |
| 234 } | |
| 235 | |
| 236 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru
ctTag) (err error) { | 224 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru
ctTag) (err error) { |
| 237 if st.substructCodec != nil { | 225 if st.substructCodec != nil { |
| 238 count, err := (&structPLS{v, st.substructCodec}).save(pr
opMap, name, si) | 226 count, err := (&structPLS{v, st.substructCodec}).save(pr
opMap, name, si) |
| 239 if err == nil { | 227 if err == nil { |
| 240 idxCount += count | 228 idxCount += count |
| 241 if idxCount > maxIndexedProperties { | 229 if idxCount > maxIndexedProperties { |
| 242 err = errors.New("gae: too many indexed
properties") | 230 err = errors.New("gae: too many indexed
properties") |
| 243 } | 231 } |
| 244 } | 232 } |
| 245 return err | 233 return err |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 } | 273 } |
| 286 } else { | 274 } else { |
| 287 if err = saveProp(name, is1, v, &st); err != nil { | 275 if err = saveProp(name, is1, v, &st); err != nil { |
| 288 return | 276 return |
| 289 } | 277 } |
| 290 } | 278 } |
| 291 } | 279 } |
| 292 return | 280 return |
| 293 } | 281 } |
| 294 | 282 |
| 295 func (p *structPLS) GetMeta(key string) (interface{}, error) { | 283 func (p *structPLS) GetMeta(key string) (interface{}, bool) { |
| 296 » if err := p.Problem(); err != nil { | |
| 297 » » return nil, err | |
| 298 » } | |
| 299 | |
| 300 if idx, ok := p.c.byMeta[key]; ok { | 284 if idx, ok := p.c.byMeta[key]; ok { |
| 301 if val, ok := p.getMetaFor(idx); ok { | 285 if val, ok := p.getMetaFor(idx); ok { |
| 302 » » » return val, nil | 286 » » » return val, true |
| 303 } | 287 } |
| 304 } else if key == "kind" { | 288 } else if key == "kind" { |
| 305 » » return p.getDefaultKind(), nil | 289 » » return p.getDefaultKind(), true |
| 306 } | 290 } |
| 307 » return nil, ErrMetaFieldUnset | 291 » return nil, false |
| 308 } | 292 } |
| 309 | 293 |
| 310 func (p *structPLS) getMetaFor(idx int) (interface{}, bool) { | 294 func (p *structPLS) getMetaFor(idx int) (interface{}, bool) { |
| 311 st := p.c.byIndex[idx] | 295 st := p.c.byIndex[idx] |
| 312 val := st.metaVal | 296 val := st.metaVal |
| 313 if st.canSet { | 297 if st.canSet { |
| 314 f := p.o.Field(idx) | 298 f := p.o.Field(idx) |
| 315 if st.convert { | 299 if st.convert { |
| 316 prop, err := f.Addr().Interface().(PropertyConverter).To
Property() | 300 prop, err := f.Addr().Interface().(PropertyConverter).To
Property() |
| 317 if err != nil { | 301 if err != nil { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 345 } | 329 } |
| 346 } | 330 } |
| 347 if needKind { | 331 if needKind { |
| 348 if _, ok := p.c.byMeta["kind"]; !ok { | 332 if _, ok := p.c.byMeta["kind"]; !ok { |
| 349 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} | 333 ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} |
| 350 } | 334 } |
| 351 } | 335 } |
| 352 return ret | 336 return ret |
| 353 } | 337 } |
| 354 | 338 |
| 355 func (p *structPLS) GetMetaDefault(key string, def interface{}) interface{} { | 339 func (p *structPLS) SetMeta(key string, val interface{}) bool { |
| 356 » return GetMetaDefaultImpl(p.GetMeta, key, def) | |
| 357 } | |
| 358 | |
| 359 func (p *structPLS) SetMeta(key string, val interface{}) (err error) { | |
| 360 » if err = p.Problem(); err != nil { | |
| 361 » » return | |
| 362 » } | |
| 363 idx, ok := p.c.byMeta[key] | 340 idx, ok := p.c.byMeta[key] |
| 364 if !ok { | 341 if !ok { |
| 365 » » return ErrMetaFieldUnset | 342 » » return false |
| 366 } | 343 } |
| 367 st := p.c.byIndex[idx] | 344 st := p.c.byIndex[idx] |
| 368 if !st.canSet { | 345 if !st.canSet { |
| 369 » » return fmt.Errorf("gae/helper: cannot set meta %q: unexported fi
eld", key) | 346 » » return false |
| 370 } | 347 } |
| 371 if st.convert { | 348 if st.convert { |
| 372 » » return p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro
mProperty( | 349 » » err := p.o.Field(idx).Addr().Interface().(PropertyConverter).Fro
mProperty( |
| 373 MkPropertyNI(val)) | 350 MkPropertyNI(val)) |
| 351 return err == nil |
| 374 } | 352 } |
| 375 | 353 |
| 376 // setting a BoolField | 354 // setting a BoolField |
| 377 if b, ok := val.(bool); ok { | 355 if b, ok := val.(bool); ok { |
| 378 if b { | 356 if b { |
| 379 val = On | 357 val = On |
| 380 } else { | 358 } else { |
| 381 val = Off | 359 val = Off |
| 382 } | 360 } |
| 383 } | 361 } |
| 384 f := p.o.Field(idx) | 362 f := p.o.Field(idx) |
| 385 if val == nil { | 363 if val == nil { |
| 386 f.Set(reflect.Zero(f.Type())) | 364 f.Set(reflect.Zero(f.Type())) |
| 387 } else { | 365 } else { |
| 388 value := reflect.ValueOf(val) | 366 value := reflect.ValueOf(val) |
| 389 f.Set(value.Convert(f.Type())) | 367 f.Set(value.Convert(f.Type())) |
| 390 } | 368 } |
| 391 » return nil | 369 » return true |
| 392 } | 370 } |
| 393 | 371 |
| 394 func (p *structPLS) Problem() error { return p.c.problem } | |
| 395 | |
| 396 var ( | 372 var ( |
| 397 // The RWMutex is chosen intentionally, as the majority of access to the | 373 // The RWMutex is chosen intentionally, as the majority of access to the |
| 398 // structCodecs map will be in parallel and will be to read an existing
codec. | 374 // structCodecs map will be in parallel and will be to read an existing
codec. |
| 399 // There's no reason to serialize goroutines on every | 375 // There's no reason to serialize goroutines on every |
| 400 // gae.Interface.{Get,Put}{,Multi} call. | 376 // gae.Interface.{Get,Put}{,Multi} call. |
| 401 structCodecsMutex sync.RWMutex | 377 structCodecsMutex sync.RWMutex |
| 402 structCodecs = map[reflect.Type]*structCodec{} | 378 structCodecs = map[reflect.Type]*structCodec{} |
| 403 ) | 379 ) |
| 404 | 380 |
| 405 // validPropertyName returns whether name consists of one or more valid Go | 381 // validPropertyName returns whether name consists of one or more valid Go |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 } | 415 } |
| 440 | 416 |
| 441 me := func(fmtStr string, args ...interface{}) error { | 417 me := func(fmtStr string, args ...interface{}) error { |
| 442 return fmt.Errorf(fmtStr, args...) | 418 return fmt.Errorf(fmtStr, args...) |
| 443 } | 419 } |
| 444 | 420 |
| 445 c = &structCodec{ | 421 c = &structCodec{ |
| 446 byIndex: make([]structTag, t.NumField()), | 422 byIndex: make([]structTag, t.NumField()), |
| 447 byName: make(map[string]int, t.NumField()), | 423 byName: make(map[string]int, t.NumField()), |
| 448 byMeta: make(map[string]int, t.NumField()), | 424 byMeta: make(map[string]int, t.NumField()), |
| 425 |
| 449 problem: errRecursiveStruct, // we'll clear this later if it's n
ot recursive | 426 problem: errRecursiveStruct, // we'll clear this later if it's n
ot recursive |
| 450 } | 427 } |
| 451 defer func() { | 428 defer func() { |
| 452 // If the codec has a problem, free up the indexes | 429 // If the codec has a problem, free up the indexes |
| 453 if c.problem != nil { | 430 if c.problem != nil { |
| 454 c.byIndex = nil | 431 c.byIndex = nil |
| 455 c.byName = nil | 432 c.byName = nil |
| 456 c.byMeta = nil | 433 c.byMeta = nil |
| 457 } | 434 } |
| 458 }() | 435 }() |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 switch val { | 583 switch val { |
| 607 case "on", "On", "true": | 584 case "on", "On", "true": |
| 608 return true, nil | 585 return true, nil |
| 609 case "off", "Off", "false": | 586 case "off", "Off", "false": |
| 610 return false, nil | 587 return false, nil |
| 611 } | 588 } |
| 612 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) | 589 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) |
| 613 } | 590 } |
| 614 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) | 591 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) |
| 615 } | 592 } |
| OLD | NEW |