]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/google.golang.org/appengine/datastore/load.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / google.golang.org / appengine / datastore / load.go
1 // Copyright 2011 Google Inc. All rights reserved.
2 // Use of this source code is governed by the Apache 2.0
3 // license that can be found in the LICENSE file.
4
5 package datastore
6
7 import (
8 "fmt"
9 "reflect"
10 "strings"
11 "time"
12
13 "github.com/golang/protobuf/proto"
14 "google.golang.org/appengine"
15 pb "google.golang.org/appengine/internal/datastore"
16 )
17
18 var (
19 typeOfBlobKey = reflect.TypeOf(appengine.BlobKey(""))
20 typeOfByteSlice = reflect.TypeOf([]byte(nil))
21 typeOfByteString = reflect.TypeOf(ByteString(nil))
22 typeOfGeoPoint = reflect.TypeOf(appengine.GeoPoint{})
23 typeOfTime = reflect.TypeOf(time.Time{})
24 typeOfKeyPtr = reflect.TypeOf(&Key{})
25 typeOfEntityPtr = reflect.TypeOf(&Entity{})
26 )
27
28 // typeMismatchReason returns a string explaining why the property p could not
29 // be stored in an entity field of type v.Type().
30 func typeMismatchReason(pValue interface{}, v reflect.Value) string {
31 entityType := "empty"
32 switch pValue.(type) {
33 case int64:
34 entityType = "int"
35 case bool:
36 entityType = "bool"
37 case string:
38 entityType = "string"
39 case float64:
40 entityType = "float"
41 case *Key:
42 entityType = "*datastore.Key"
43 case time.Time:
44 entityType = "time.Time"
45 case appengine.BlobKey:
46 entityType = "appengine.BlobKey"
47 case appengine.GeoPoint:
48 entityType = "appengine.GeoPoint"
49 case ByteString:
50 entityType = "datastore.ByteString"
51 case []byte:
52 entityType = "[]byte"
53 }
54 return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type())
55 }
56
57 type propertyLoader struct {
58 // m holds the number of times a substruct field like "Foo.Bar.Baz" has
59 // been seen so far. The map is constructed lazily.
60 m map[string]int
61 }
62
63 func (l *propertyLoader) load(codec *structCodec, structValue reflect.Value, p Property, requireSlice bool) string {
64 var v reflect.Value
65 var sliceIndex int
66
67 name := p.Name
68
69 // If name ends with a '.', the last field is anonymous.
70 // In this case, strings.Split will give us "" as the
71 // last element of our fields slice, which will match the ""
72 // field name in the substruct codec.
73 fields := strings.Split(name, ".")
74
75 for len(fields) > 0 {
76 var decoder fieldCodec
77 var ok bool
78
79 // Cut off the last field (delimited by ".") and find its parent
80 // in the codec.
81 // eg. for name "A.B.C.D", split off "A.B.C" and try to
82 // find a field in the codec with this name.
83 // Loop again with "A.B", etc.
84 for i := len(fields); i > 0; i-- {
85 parent := strings.Join(fields[:i], ".")
86 decoder, ok = codec.fields[parent]
87 if ok {
88 fields = fields[i:]
89 break
90 }
91 }
92
93 // If we never found a matching field in the codec, return
94 // error message.
95 if !ok {
96 return "no such struct field"
97 }
98
99 v = initField(structValue, decoder.path)
100 if !v.IsValid() {
101 return "no such struct field"
102 }
103 if !v.CanSet() {
104 return "cannot set struct field"
105 }
106
107 if decoder.structCodec != nil {
108 codec = decoder.structCodec
109 structValue = v
110 }
111
112 if v.Kind() == reflect.Slice && v.Type() != typeOfByteSlice {
113 if l.m == nil {
114 l.m = make(map[string]int)
115 }
116 sliceIndex = l.m[p.Name]
117 l.m[p.Name] = sliceIndex + 1
118 for v.Len() <= sliceIndex {
119 v.Set(reflect.Append(v, reflect.New(v.Type().Elem()).Elem()))
120 }
121 structValue = v.Index(sliceIndex)
122 requireSlice = false
123 }
124 }
125
126 var slice reflect.Value
127 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
128 slice = v
129 v = reflect.New(v.Type().Elem()).Elem()
130 } else if requireSlice {
131 return "multiple-valued property requires a slice field type"
132 }
133
134 // Convert indexValues to a Go value with a meaning derived from the
135 // destination type.
136 pValue := p.Value
137 if iv, ok := pValue.(indexValue); ok {
138 meaning := pb.Property_NO_MEANING
139 switch v.Type() {
140 case typeOfBlobKey:
141 meaning = pb.Property_BLOBKEY
142 case typeOfByteSlice:
143 meaning = pb.Property_BLOB
144 case typeOfByteString:
145 meaning = pb.Property_BYTESTRING
146 case typeOfGeoPoint:
147 meaning = pb.Property_GEORSS_POINT
148 case typeOfTime:
149 meaning = pb.Property_GD_WHEN
150 case typeOfEntityPtr:
151 meaning = pb.Property_ENTITY_PROTO
152 }
153 var err error
154 pValue, err = propValue(iv.value, meaning)
155 if err != nil {
156 return err.Error()
157 }
158 }
159
160 if errReason := setVal(v, pValue); errReason != "" {
161 // Set the slice back to its zero value.
162 if slice.IsValid() {
163 slice.Set(reflect.Zero(slice.Type()))
164 }
165 return errReason
166 }
167
168 if slice.IsValid() {
169 slice.Index(sliceIndex).Set(v)
170 }
171
172 return ""
173 }
174
175 // setVal sets v to the value pValue.
176 func setVal(v reflect.Value, pValue interface{}) string {
177 switch v.Kind() {
178 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
179 x, ok := pValue.(int64)
180 if !ok && pValue != nil {
181 return typeMismatchReason(pValue, v)
182 }
183 if v.OverflowInt(x) {
184 return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type())
185 }
186 v.SetInt(x)
187 case reflect.Bool:
188 x, ok := pValue.(bool)
189 if !ok && pValue != nil {
190 return typeMismatchReason(pValue, v)
191 }
192 v.SetBool(x)
193 case reflect.String:
194 switch x := pValue.(type) {
195 case appengine.BlobKey:
196 v.SetString(string(x))
197 case ByteString:
198 v.SetString(string(x))
199 case string:
200 v.SetString(x)
201 default:
202 if pValue != nil {
203 return typeMismatchReason(pValue, v)
204 }
205 }
206 case reflect.Float32, reflect.Float64:
207 x, ok := pValue.(float64)
208 if !ok && pValue != nil {
209 return typeMismatchReason(pValue, v)
210 }
211 if v.OverflowFloat(x) {
212 return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type())
213 }
214 v.SetFloat(x)
215 case reflect.Ptr:
216 x, ok := pValue.(*Key)
217 if !ok && pValue != nil {
218 return typeMismatchReason(pValue, v)
219 }
220 if _, ok := v.Interface().(*Key); !ok {
221 return typeMismatchReason(pValue, v)
222 }
223 v.Set(reflect.ValueOf(x))
224 case reflect.Struct:
225 switch v.Type() {
226 case typeOfTime:
227 x, ok := pValue.(time.Time)
228 if !ok && pValue != nil {
229 return typeMismatchReason(pValue, v)
230 }
231 v.Set(reflect.ValueOf(x))
232 case typeOfGeoPoint:
233 x, ok := pValue.(appengine.GeoPoint)
234 if !ok && pValue != nil {
235 return typeMismatchReason(pValue, v)
236 }
237 v.Set(reflect.ValueOf(x))
238 default:
239 ent, ok := pValue.(*Entity)
240 if !ok {
241 return typeMismatchReason(pValue, v)
242 }
243
244 // Recursively load nested struct
245 pls, err := newStructPLS(v.Addr().Interface())
246 if err != nil {
247 return err.Error()
248 }
249
250 // if ent has a Key value and our struct has a Key field,
251 // load the Entity's Key value into the Key field on the struct.
252 if ent.Key != nil && pls.codec.keyField != -1 {
253
254 pls.v.Field(pls.codec.keyField).Set(reflect.ValueOf(ent.Key))
255 }
256
257 err = pls.Load(ent.Properties)
258 if err != nil {
259 return err.Error()
260 }
261 }
262 case reflect.Slice:
263 x, ok := pValue.([]byte)
264 if !ok {
265 if y, yok := pValue.(ByteString); yok {
266 x, ok = []byte(y), true
267 }
268 }
269 if !ok && pValue != nil {
270 return typeMismatchReason(pValue, v)
271 }
272 if v.Type().Elem().Kind() != reflect.Uint8 {
273 return typeMismatchReason(pValue, v)
274 }
275 v.SetBytes(x)
276 default:
277 return typeMismatchReason(pValue, v)
278 }
279 return ""
280 }
281
282 // initField is similar to reflect's Value.FieldByIndex, in that it
283 // returns the nested struct field corresponding to index, but it
284 // initialises any nil pointers encountered when traversing the structure.
285 func initField(val reflect.Value, index []int) reflect.Value {
286 for _, i := range index[:len(index)-1] {
287 val = val.Field(i)
288 if val.Kind() == reflect.Ptr {
289 if val.IsNil() {
290 val.Set(reflect.New(val.Type().Elem()))
291 }
292 val = val.Elem()
293 }
294 }
295 return val.Field(index[len(index)-1])
296 }
297
298 // loadEntity loads an EntityProto into PropertyLoadSaver or struct pointer.
299 func loadEntity(dst interface{}, src *pb.EntityProto) (err error) {
300 ent, err := protoToEntity(src)
301 if err != nil {
302 return err
303 }
304 if e, ok := dst.(PropertyLoadSaver); ok {
305 return e.Load(ent.Properties)
306 }
307 return LoadStruct(dst, ent.Properties)
308 }
309
310 func (s structPLS) Load(props []Property) error {
311 var fieldName, reason string
312 var l propertyLoader
313 for _, p := range props {
314 if errStr := l.load(s.codec, s.v, p, p.Multiple); errStr != "" {
315 // We don't return early, as we try to load as many properties as possible.
316 // It is valid to load an entity into a struct that cannot fully represent it.
317 // That case returns an error, but the caller is free to ignore it.
318 fieldName, reason = p.Name, errStr
319 }
320 }
321 if reason != "" {
322 return &ErrFieldMismatch{
323 StructType: s.v.Type(),
324 FieldName: fieldName,
325 Reason: reason,
326 }
327 }
328 return nil
329 }
330
331 func protoToEntity(src *pb.EntityProto) (*Entity, error) {
332 props, rawProps := src.Property, src.RawProperty
333 outProps := make([]Property, 0, len(props)+len(rawProps))
334 for {
335 var (
336 x *pb.Property
337 noIndex bool
338 )
339 if len(props) > 0 {
340 x, props = props[0], props[1:]
341 } else if len(rawProps) > 0 {
342 x, rawProps = rawProps[0], rawProps[1:]
343 noIndex = true
344 } else {
345 break
346 }
347
348 var value interface{}
349 if x.Meaning != nil && *x.Meaning == pb.Property_INDEX_VALUE {
350 value = indexValue{x.Value}
351 } else {
352 var err error
353 value, err = propValue(x.Value, x.GetMeaning())
354 if err != nil {
355 return nil, err
356 }
357 }
358 outProps = append(outProps, Property{
359 Name: x.GetName(),
360 Value: value,
361 NoIndex: noIndex,
362 Multiple: x.GetMultiple(),
363 })
364 }
365
366 var key *Key
367 if src.Key != nil {
368 // Ignore any error, since nested entity values
369 // are allowed to have an invalid key.
370 key, _ = protoToKey(src.Key)
371 }
372 return &Entity{key, outProps}, nil
373 }
374
375 // propValue returns a Go value that combines the raw PropertyValue with a
376 // meaning. For example, an Int64Value with GD_WHEN becomes a time.Time.
377 func propValue(v *pb.PropertyValue, m pb.Property_Meaning) (interface{}, error) {
378 switch {
379 case v.Int64Value != nil:
380 if m == pb.Property_GD_WHEN {
381 return fromUnixMicro(*v.Int64Value), nil
382 } else {
383 return *v.Int64Value, nil
384 }
385 case v.BooleanValue != nil:
386 return *v.BooleanValue, nil
387 case v.StringValue != nil:
388 if m == pb.Property_BLOB {
389 return []byte(*v.StringValue), nil
390 } else if m == pb.Property_BLOBKEY {
391 return appengine.BlobKey(*v.StringValue), nil
392 } else if m == pb.Property_BYTESTRING {
393 return ByteString(*v.StringValue), nil
394 } else if m == pb.Property_ENTITY_PROTO {
395 var ent pb.EntityProto
396 err := proto.Unmarshal([]byte(*v.StringValue), &ent)
397 if err != nil {
398 return nil, err
399 }
400 return protoToEntity(&ent)
401 } else {
402 return *v.StringValue, nil
403 }
404 case v.DoubleValue != nil:
405 return *v.DoubleValue, nil
406 case v.Referencevalue != nil:
407 key, err := referenceValueToKey(v.Referencevalue)
408 if err != nil {
409 return nil, err
410 }
411 return key, nil
412 case v.Pointvalue != nil:
413 // NOTE: Strangely, latitude maps to X, longitude to Y.
414 return appengine.GeoPoint{Lat: v.Pointvalue.GetX(), Lng: v.Pointvalue.GetY()}, nil
415 }
416 return nil, nil
417 }
418
419 // indexValue is a Property value that is created when entities are loaded from
420 // an index, such as from a projection query.
421 //
422 // Such Property values do not contain all of the metadata required to be
423 // faithfully represented as a Go value, and are instead represented as an
424 // opaque indexValue. Load the properties into a concrete struct type (e.g. by
425 // passing a struct pointer to Iterator.Next) to reconstruct actual Go values
426 // of type int, string, time.Time, etc.
427 type indexValue struct {
428 value *pb.PropertyValue
429 }