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 package datastore | 5 package datastore |
6 | 6 |
7 import ( | 7 import ( |
8 "reflect" | 8 "reflect" |
9 ) | 9 ) |
10 | 10 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 // struct Comment { | 79 // struct Comment { |
80 // ID int64 `gae:"$id"` | 80 // ID int64 `gae:"$id"` |
81 // // "kind" is automatically implied by the struct name: "Comment" | 81 // // "kind" is automatically implied by the struct name: "Comment" |
82 // | 82 // |
83 // // Parent will be enforced by the application to be a User key. | 83 // // Parent will be enforced by the application to be a User key. |
84 // Parent Key `gae:"$parent"` | 84 // Parent Key `gae:"$parent"` |
85 // | 85 // |
86 // // 'Lines' will serialized to the datastore in the field 'Lines' | 86 // // 'Lines' will serialized to the datastore in the field 'Lines' |
87 // Lines []string | 87 // Lines []string |
88 // } | 88 // } |
| 89 // |
| 90 // A pointer-to-struct may also implement MetaGetterSetter to provide more |
| 91 // sophistocated metadata values. Explicitly defined fields (as shown above) |
| 92 // always take precedence over fields manipulated by the MetaGetterSetter |
| 93 // methods. So if your GetMeta handles "kind", but you explicitly have a |
| 94 // $kind field, the $kind field will take precedence and your GetMeta |
| 95 // implementation will not be called for "kind". |
89 func GetPLS(obj interface{}) PropertyLoadSaver { | 96 func GetPLS(obj interface{}) PropertyLoadSaver { |
90 v := reflect.ValueOf(obj) | 97 v := reflect.ValueOf(obj) |
91 if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { | 98 if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { |
92 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} | 99 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} |
93 } | 100 } |
94 if v.IsNil() { | 101 if v.IsNil() { |
95 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} | 102 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} |
96 } | 103 } |
97 v = v.Elem() | 104 v = v.Elem() |
98 c := getCodec(v.Type()) | 105 c := getCodec(v.Type()) |
99 return &structPLS{v, c} | 106 return &structPLS{v, c} |
100 } | 107 } |
101 | 108 |
102 func getCodec(structType reflect.Type) *structCodec { | 109 func getCodec(structType reflect.Type) *structCodec { |
103 structCodecsMutex.RLock() | 110 structCodecsMutex.RLock() |
104 c, ok := structCodecs[structType] | 111 c, ok := structCodecs[structType] |
105 structCodecsMutex.RUnlock() | 112 structCodecsMutex.RUnlock() |
106 if ok { | 113 if ok { |
107 return c | 114 return c |
108 } | 115 } |
109 | 116 |
110 structCodecsMutex.Lock() | 117 structCodecsMutex.Lock() |
111 defer structCodecsMutex.Unlock() | 118 defer structCodecsMutex.Unlock() |
112 return getStructCodecLocked(structType) | 119 return getStructCodecLocked(structType) |
113 } | 120 } |
OLD | NEW |