prop.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. "strings"
  19. "sync"
  20. "unicode"
  21. )
  22. // Entities with more than this many indexed properties will not be saved.
  23. const maxIndexedProperties = 5000
  24. // []byte fields more than 1 megabyte long will not be loaded or saved.
  25. const maxBlobLen = 1 << 20
  26. // Property is a name/value pair plus some metadata. A datastore entity's
  27. // contents are loaded and saved as a sequence of Properties. An entity can
  28. // have multiple Properties with the same name, provided that p.Multiple is
  29. // true on all of that entity's Properties with that name.
  30. type Property struct {
  31. // Name is the property name.
  32. Name string
  33. // Value is the property value. The valid types are:
  34. // - int64
  35. // - bool
  36. // - string
  37. // - float64
  38. // - *Key
  39. // - time.Time
  40. // - []byte (up to 1 megabyte in length)
  41. // This set is smaller than the set of valid struct field types that the
  42. // datastore can load and save. A Property Value cannot be a slice (apart
  43. // from []byte); use multiple Properties instead. Also, a Value's type
  44. // must be explicitly on the list above; it is not sufficient for the
  45. // underlying type to be on that list. For example, a Value of "type
  46. // myInt64 int64" is invalid. Smaller-width integers and floats are also
  47. // invalid. Again, this is more restrictive than the set of valid struct
  48. // field types.
  49. //
  50. // A Value will have an opaque type when loading entities from an index,
  51. // such as via a projection query. Load entities into a struct instead
  52. // of a PropertyLoadSaver when using a projection query.
  53. //
  54. // A Value may also be the nil interface value; this is equivalent to
  55. // Python's None but not directly representable by a Go struct. Loading
  56. // a nil-valued property into a struct will set that field to the zero
  57. // value.
  58. Value interface{}
  59. // NoIndex is whether the datastore cannot index this property.
  60. // If NoIndex is set to false, []byte values are limited to 1500 bytes and
  61. // string values are limited to 1500 bytes.
  62. NoIndex bool
  63. // Multiple is whether the entity can have multiple properties with
  64. // the same name. Even if a particular instance only has one property with
  65. // a certain name, Multiple should be true if a struct would best represent
  66. // it as a field of type []T instead of type T.
  67. Multiple bool
  68. }
  69. // PropertyLoadSaver can be converted from and to a slice of Properties.
  70. type PropertyLoadSaver interface {
  71. Load([]Property) error
  72. Save() ([]Property, error)
  73. }
  74. // PropertyList converts a []Property to implement PropertyLoadSaver.
  75. type PropertyList []Property
  76. var (
  77. typeOfPropertyLoadSaver = reflect.TypeOf((*PropertyLoadSaver)(nil)).Elem()
  78. typeOfPropertyList = reflect.TypeOf(PropertyList(nil))
  79. )
  80. // Load loads all of the provided properties into l.
  81. // It does not first reset *l to an empty slice.
  82. func (l *PropertyList) Load(p []Property) error {
  83. *l = append(*l, p...)
  84. return nil
  85. }
  86. // Save saves all of l's properties as a slice of Properties.
  87. func (l *PropertyList) Save() ([]Property, error) {
  88. return *l, nil
  89. }
  90. // validPropertyName returns whether name consists of one or more valid Go
  91. // identifiers joined by ".".
  92. func validPropertyName(name string) bool {
  93. if name == "" {
  94. return false
  95. }
  96. for _, s := range strings.Split(name, ".") {
  97. if s == "" {
  98. return false
  99. }
  100. first := true
  101. for _, c := range s {
  102. if first {
  103. first = false
  104. if c != '_' && !unicode.IsLetter(c) {
  105. return false
  106. }
  107. } else {
  108. if c != '_' && !unicode.IsLetter(c) && !unicode.IsDigit(c) {
  109. return false
  110. }
  111. }
  112. }
  113. }
  114. return true
  115. }
  116. // structTag is the parsed `datastore:"name,options"` tag of a struct field.
  117. // If a field has no tag, or the tag has an empty name, then the structTag's
  118. // name is just the field name. A "-" name means that the datastore ignores
  119. // that field.
  120. type structTag struct {
  121. name string
  122. noIndex bool
  123. }
  124. // structCodec describes how to convert a struct to and from a sequence of
  125. // properties.
  126. type structCodec struct {
  127. // byIndex gives the structTag for the i'th field.
  128. byIndex []structTag
  129. // byName gives the field codec for the structTag with the given name.
  130. byName map[string]fieldCodec
  131. // hasSlice is whether a struct or any of its nested or embedded structs
  132. // has a slice-typed field (other than []byte).
  133. hasSlice bool
  134. // complete is whether the structCodec is complete. An incomplete
  135. // structCodec may be encountered when walking a recursive struct.
  136. complete bool
  137. }
  138. // fieldCodec is a struct field's index and, if that struct field's type is
  139. // itself a struct, that substruct's structCodec.
  140. type fieldCodec struct {
  141. index int
  142. substructCodec *structCodec
  143. }
  144. // structCodecs collects the structCodecs that have already been calculated.
  145. var (
  146. structCodecsMutex sync.Mutex
  147. structCodecs = make(map[reflect.Type]*structCodec)
  148. )
  149. // getStructCodec returns the structCodec for the given struct type.
  150. func getStructCodec(t reflect.Type) (*structCodec, error) {
  151. structCodecsMutex.Lock()
  152. defer structCodecsMutex.Unlock()
  153. return getStructCodecLocked(t)
  154. }
  155. // getStructCodecLocked implements getStructCodec. The structCodecsMutex must
  156. // be held when calling this function.
  157. func getStructCodecLocked(t reflect.Type) (ret *structCodec, retErr error) {
  158. c, ok := structCodecs[t]
  159. if ok {
  160. return c, nil
  161. }
  162. c = &structCodec{
  163. byIndex: make([]structTag, t.NumField()),
  164. byName: make(map[string]fieldCodec),
  165. }
  166. // Add c to the structCodecs map before we are sure it is good. If t is
  167. // a recursive type, it needs to find the incomplete entry for itself in
  168. // the map.
  169. structCodecs[t] = c
  170. defer func() {
  171. if retErr != nil {
  172. delete(structCodecs, t)
  173. }
  174. }()
  175. for i := range c.byIndex {
  176. f := t.Field(i)
  177. name, opts := f.Tag.Get("datastore"), ""
  178. if i := strings.Index(name, ","); i != -1 {
  179. name, opts = name[:i], name[i+1:]
  180. }
  181. if name == "" {
  182. if !f.Anonymous {
  183. name = f.Name
  184. }
  185. } else if name == "-" {
  186. c.byIndex[i] = structTag{name: name}
  187. continue
  188. } else if !validPropertyName(name) {
  189. return nil, fmt.Errorf("datastore: struct tag has invalid property name: %q", name)
  190. }
  191. substructType, fIsSlice := reflect.Type(nil), false
  192. switch f.Type.Kind() {
  193. case reflect.Struct:
  194. substructType = f.Type
  195. case reflect.Slice:
  196. if f.Type.Elem().Kind() == reflect.Struct {
  197. substructType = f.Type.Elem()
  198. }
  199. fIsSlice = f.Type != typeOfByteSlice
  200. c.hasSlice = c.hasSlice || fIsSlice
  201. }
  202. if substructType != nil && substructType != typeOfTime {
  203. if name != "" {
  204. name = name + "."
  205. }
  206. sub, err := getStructCodecLocked(substructType)
  207. if err != nil {
  208. return nil, err
  209. }
  210. if !sub.complete {
  211. return nil, fmt.Errorf("datastore: recursive struct: field %q", f.Name)
  212. }
  213. if fIsSlice && sub.hasSlice {
  214. return nil, fmt.Errorf(
  215. "datastore: flattening nested structs leads to a slice of slices: field %q", f.Name)
  216. }
  217. c.hasSlice = c.hasSlice || sub.hasSlice
  218. for relName := range sub.byName {
  219. absName := name + relName
  220. if _, ok := c.byName[absName]; ok {
  221. return nil, fmt.Errorf("datastore: struct tag has repeated property name: %q", absName)
  222. }
  223. c.byName[absName] = fieldCodec{index: i, substructCodec: sub}
  224. }
  225. } else {
  226. if _, ok := c.byName[name]; ok {
  227. return nil, fmt.Errorf("datastore: struct tag has repeated property name: %q", name)
  228. }
  229. c.byName[name] = fieldCodec{index: i}
  230. }
  231. c.byIndex[i] = structTag{
  232. name: name,
  233. noIndex: opts == "noindex",
  234. }
  235. }
  236. c.complete = true
  237. return c, nil
  238. }
  239. // structPLS adapts a struct to be a PropertyLoadSaver.
  240. type structPLS struct {
  241. v reflect.Value
  242. codec *structCodec
  243. }
  244. // newStructPLS returns a PropertyLoadSaver for the struct pointer p.
  245. func newStructPLS(p interface{}) (PropertyLoadSaver, error) {
  246. v := reflect.ValueOf(p)
  247. if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
  248. return nil, ErrInvalidEntityType
  249. }
  250. v = v.Elem()
  251. codec, err := getStructCodec(v.Type())
  252. if err != nil {
  253. return nil, err
  254. }
  255. return structPLS{v, codec}, nil
  256. }
  257. // LoadStruct loads the properties from p to dst.
  258. // dst must be a struct pointer.
  259. func LoadStruct(dst interface{}, p []Property) error {
  260. x, err := newStructPLS(dst)
  261. if err != nil {
  262. return err
  263. }
  264. return x.Load(p)
  265. }
  266. // SaveStruct returns the properties from src as a slice of Properties.
  267. // src must be a struct pointer.
  268. func SaveStruct(src interface{}) ([]Property, error) {
  269. x, err := newStructPLS(src)
  270. if err != nil {
  271. return nil, err
  272. }
  273. return x.Save()
  274. }