load.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package datastore
  15. import (
  16. "fmt"
  17. "reflect"
  18. "time"
  19. pb "google.golang.org/cloud/internal/datastore"
  20. )
  21. var (
  22. typeOfByteSlice = reflect.TypeOf([]byte(nil))
  23. typeOfTime = reflect.TypeOf(time.Time{})
  24. )
  25. // typeMismatchReason returns a string explaining why the property p could not
  26. // be stored in an entity field of type v.Type().
  27. func typeMismatchReason(p Property, v reflect.Value) string {
  28. entityType := "empty"
  29. switch p.Value.(type) {
  30. case int64:
  31. entityType = "int"
  32. case bool:
  33. entityType = "bool"
  34. case string:
  35. entityType = "string"
  36. case float64:
  37. entityType = "float"
  38. case *Key:
  39. entityType = "*datastore.Key"
  40. case time.Time:
  41. entityType = "time.Time"
  42. case []byte:
  43. entityType = "[]byte"
  44. }
  45. return fmt.Sprintf("type mismatch: %s versus %v", entityType, v.Type())
  46. }
  47. type propertyLoader struct {
  48. // m holds the number of times a substruct field like "Foo.Bar.Baz" has
  49. // been seen so far. The map is constructed lazily.
  50. m map[string]int
  51. }
  52. func (l *propertyLoader) load(codec *structCodec, structValue reflect.Value, p Property, prev map[string]struct{}) string {
  53. var sliceOk bool
  54. var v reflect.Value
  55. // Traverse a struct's struct-typed fields.
  56. for name := p.Name; ; {
  57. decoder, ok := codec.byName[name]
  58. if !ok {
  59. return "no such struct field"
  60. }
  61. v = structValue.Field(decoder.index)
  62. if !v.IsValid() {
  63. return "no such struct field"
  64. }
  65. if !v.CanSet() {
  66. return "cannot set struct field"
  67. }
  68. if decoder.substructCodec == nil {
  69. break
  70. }
  71. if v.Kind() == reflect.Slice {
  72. if l.m == nil {
  73. l.m = make(map[string]int)
  74. }
  75. index := l.m[p.Name]
  76. l.m[p.Name] = index + 1
  77. for v.Len() <= index {
  78. v.Set(reflect.Append(v, reflect.New(v.Type().Elem()).Elem()))
  79. }
  80. structValue = v.Index(index)
  81. sliceOk = true
  82. } else {
  83. structValue = v
  84. }
  85. // Strip the "I." from "I.X".
  86. name = name[len(codec.byIndex[decoder.index].name):]
  87. codec = decoder.substructCodec
  88. }
  89. var slice reflect.Value
  90. if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
  91. slice = v
  92. v = reflect.New(v.Type().Elem()).Elem()
  93. } else if _, ok := prev[p.Name]; ok && !sliceOk {
  94. // Zero the field back out that was set previously, turns out its a slice and we don't know what to do with it
  95. v.Set(reflect.Zero(v.Type()))
  96. return "multiple-valued property requires a slice field type"
  97. }
  98. prev[p.Name] = struct{}{}
  99. pValue := p.Value
  100. switch v.Kind() {
  101. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  102. x, ok := pValue.(int64)
  103. if !ok && pValue != nil {
  104. return typeMismatchReason(p, v)
  105. }
  106. if v.OverflowInt(x) {
  107. return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type())
  108. }
  109. v.SetInt(x)
  110. case reflect.Bool:
  111. x, ok := pValue.(bool)
  112. if !ok && pValue != nil {
  113. return typeMismatchReason(p, v)
  114. }
  115. v.SetBool(x)
  116. case reflect.String:
  117. x, ok := pValue.(string)
  118. if !ok && pValue != nil {
  119. return typeMismatchReason(p, v)
  120. }
  121. v.SetString(x)
  122. case reflect.Float32, reflect.Float64:
  123. x, ok := pValue.(float64)
  124. if !ok && pValue != nil {
  125. return typeMismatchReason(p, v)
  126. }
  127. if v.OverflowFloat(x) {
  128. return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type())
  129. }
  130. v.SetFloat(x)
  131. case reflect.Ptr:
  132. x, ok := pValue.(*Key)
  133. if !ok && pValue != nil {
  134. return typeMismatchReason(p, v)
  135. }
  136. if _, ok := v.Interface().(*Key); !ok {
  137. return typeMismatchReason(p, v)
  138. }
  139. v.Set(reflect.ValueOf(x))
  140. case reflect.Struct:
  141. switch v.Type() {
  142. case typeOfTime:
  143. x, ok := pValue.(time.Time)
  144. if !ok && pValue != nil {
  145. return typeMismatchReason(p, v)
  146. }
  147. v.Set(reflect.ValueOf(x))
  148. default:
  149. return typeMismatchReason(p, v)
  150. }
  151. case reflect.Slice:
  152. x, ok := pValue.([]byte)
  153. if !ok && pValue != nil {
  154. return typeMismatchReason(p, v)
  155. }
  156. if v.Type().Elem().Kind() != reflect.Uint8 {
  157. return typeMismatchReason(p, v)
  158. }
  159. v.SetBytes(x)
  160. default:
  161. return typeMismatchReason(p, v)
  162. }
  163. if slice.IsValid() {
  164. slice.Set(reflect.Append(slice, v))
  165. }
  166. return ""
  167. }
  168. // loadEntity loads an EntityProto into PropertyLoadSaver or struct pointer.
  169. func loadEntity(dst interface{}, src *pb.Entity) (err error) {
  170. props := protoToProperties(src)
  171. if e, ok := dst.(PropertyLoadSaver); ok {
  172. return e.Load(props)
  173. }
  174. return LoadStruct(dst, props)
  175. }
  176. func (s structPLS) Load(props []Property) error {
  177. var fieldName, reason string
  178. var l propertyLoader
  179. prev := make(map[string]struct{})
  180. for _, p := range props {
  181. if errStr := l.load(s.codec, s.v, p, prev); errStr != "" {
  182. // We don't return early, as we try to load as many properties as possible.
  183. // It is valid to load an entity into a struct that cannot fully represent it.
  184. // That case returns an error, but the caller is free to ignore it.
  185. fieldName, reason = p.Name, errStr
  186. }
  187. }
  188. if reason != "" {
  189. return &ErrFieldMismatch{
  190. StructType: s.v.Type(),
  191. FieldName: fieldName,
  192. Reason: reason,
  193. }
  194. }
  195. return nil
  196. }
  197. func protoToProperties(src *pb.Entity) []Property {
  198. props := src.Property
  199. out := make([]Property, 0, len(props))
  200. for {
  201. var (
  202. x *pb.Property
  203. noIndex bool
  204. )
  205. if len(props) > 0 {
  206. x, props = props[0], props[1:]
  207. noIndex = !x.GetValue().GetIndexed()
  208. } else {
  209. break
  210. }
  211. if x.Value.ListValue == nil {
  212. out = append(out, Property{
  213. Name: x.GetName(),
  214. Value: propValue(x.Value),
  215. NoIndex: noIndex,
  216. Multiple: false,
  217. })
  218. } else {
  219. for _, v := range x.Value.ListValue {
  220. out = append(out, Property{
  221. Name: x.GetName(),
  222. Value: propValue(v),
  223. NoIndex: noIndex,
  224. Multiple: true,
  225. })
  226. }
  227. }
  228. }
  229. return out
  230. }
  231. // propValue returns a Go value that combines the raw PropertyValue with a
  232. // meaning. For example, an Int64Value with GD_WHEN becomes a time.Time.
  233. func propValue(v *pb.Value) interface{} {
  234. //TODO(PSG-Luna): Support EntityValue
  235. //TODO(PSG-Luna): GeoPoint seems gone from the v1 proto, reimplement it once it's readded
  236. switch {
  237. case v.IntegerValue != nil:
  238. return *v.IntegerValue
  239. case v.TimestampMicrosecondsValue != nil:
  240. return fromUnixMicro(*v.TimestampMicrosecondsValue)
  241. case v.BooleanValue != nil:
  242. return *v.BooleanValue
  243. case v.StringValue != nil:
  244. return *v.StringValue
  245. case v.BlobValue != nil:
  246. return []byte(v.BlobValue)
  247. case v.BlobKeyValue != nil:
  248. return *v.BlobKeyValue
  249. case v.DoubleValue != nil:
  250. return *v.DoubleValue
  251. case v.KeyValue != nil:
  252. // TODO(djd): Don't drop this error.
  253. key, _ := protoToKey(v.KeyValue)
  254. return key
  255. }
  256. return nil
  257. }