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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 // if err != nil { | 118 // if err != nil { |
119 // return nil, err | 119 // return nil, err |
120 // } | 120 // } |
121 // props["foo"] = []Property{MkProperty(s.foo)} | 121 // props["foo"] = []Property{MkProperty(s.foo)} |
122 // return props, nil | 122 // return props, nil |
123 // } | 123 // } |
124 // | 124 // |
125 // func (s *Special) Problem() error { | 125 // func (s *Special) Problem() error { |
126 // return GetPLS(s).Problem() | 126 // return GetPLS(s).Problem() |
127 // } | 127 // } |
| 128 // |
| 129 // Additionally, any field ptr-to-type may implement the PropertyConverter |
| 130 // interface to allow a single field to, for example, implement some alternate |
| 131 // encoding (json, gzip), or even just serialize to/from a simple string field. |
| 132 // This applies to normal fields, as well as metadata fields. It can be useful |
| 133 // for storing struct '$id's which have multi-field meanings. For example, the |
| 134 // Person struct below could be initialized in go as `&Person{Name{"Jane", |
| 135 // "Doe"}}`, retaining Jane's name as manipulable Go fields. However, in the |
| 136 // datastore, it would have a key of `/Person,"Jane|Doe"`, and loading the |
| 137 // struct from the datastore as part of a Query, for example, would correctly |
| 138 // populate Person.Name.First and Person.Name.Last. |
| 139 // |
| 140 // type Name struct { |
| 141 // First string |
| 142 // Last string |
| 143 // } |
| 144 // |
| 145 // func (n *Name) ToProperty() (Property, error) { |
| 146 // return fmt.Sprintf("%s|%s", n.First, n.Last) |
| 147 // } |
| 148 // |
| 149 // func (n *Name) FromProperty(p Property) error { |
| 150 // // check p to be a PTString |
| 151 // // split on "|" |
| 152 // // assign to n.First, n.Last |
| 153 // } |
| 154 // |
| 155 // type Person struct { |
| 156 // Name `gae:"$id"` |
| 157 // } |
128 func GetPLS(obj interface{}) interface { | 158 func GetPLS(obj interface{}) interface { |
129 PropertyLoadSaver | 159 PropertyLoadSaver |
130 MetaGetterSetter | 160 MetaGetterSetter |
131 } { | 161 } { |
132 v := reflect.ValueOf(obj) | 162 v := reflect.ValueOf(obj) |
133 if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { | 163 if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { |
134 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} | 164 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} |
135 } | 165 } |
136 if v.IsNil() { | 166 if v.IsNil() { |
137 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} | 167 return &structPLS{c: &structCodec{problem: ErrInvalidEntityType}
} |
(...skipping 15 matching lines...) Expand all Loading... |
153 c, ok := structCodecs[structType] | 183 c, ok := structCodecs[structType] |
154 structCodecsMutex.RUnlock() | 184 structCodecsMutex.RUnlock() |
155 if ok { | 185 if ok { |
156 return c | 186 return c |
157 } | 187 } |
158 | 188 |
159 structCodecsMutex.Lock() | 189 structCodecsMutex.Lock() |
160 defer structCodecsMutex.Unlock() | 190 defer structCodecsMutex.Unlock() |
161 return getStructCodecLocked(structType) | 191 return getStructCodecLocked(structType) |
162 } | 192 } |
OLD | NEW |