encode_field.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package impl
  5. import (
  6. "fmt"
  7. "reflect"
  8. "unicode/utf8"
  9. "google.golang.org/protobuf/internal/encoding/wire"
  10. "google.golang.org/protobuf/proto"
  11. pref "google.golang.org/protobuf/reflect/protoreflect"
  12. )
  13. type errInvalidUTF8 struct{}
  14. func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" }
  15. func (errInvalidUTF8) InvalidUTF8() bool { return true }
  16. func makeOneofFieldCoder(fs reflect.StructField, od pref.OneofDescriptor, structFields map[pref.FieldNumber]reflect.StructField, otypes map[pref.FieldNumber]reflect.Type) pointerCoderFuncs {
  17. type oneofFieldInfo struct {
  18. wiretag uint64
  19. tagsize int
  20. funcs pointerCoderFuncs
  21. }
  22. oneofFieldInfos := make(map[reflect.Type]oneofFieldInfo)
  23. for i, fields := 0, od.Fields(); i < fields.Len(); i++ {
  24. fd := fields.Get(i)
  25. ot := otypes[fd.Number()]
  26. wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
  27. oneofFieldInfos[ot] = oneofFieldInfo{
  28. wiretag: wiretag,
  29. tagsize: wire.SizeVarint(wiretag),
  30. funcs: fieldCoder(fd, ot.Field(0).Type),
  31. }
  32. }
  33. ft := fs.Type
  34. getInfo := func(p pointer) (pointer, oneofFieldInfo) {
  35. v := p.AsValueOf(ft).Elem()
  36. if v.IsNil() {
  37. return pointer{}, oneofFieldInfo{}
  38. }
  39. v = v.Elem() // interface -> *struct
  40. telem := v.Elem().Type()
  41. info, ok := oneofFieldInfos[telem]
  42. if !ok {
  43. panic(fmt.Errorf("invalid oneof type %v", telem))
  44. }
  45. return pointerOfValue(v).Apply(zeroOffset), info
  46. }
  47. return pointerCoderFuncs{
  48. size: func(p pointer, _ int, opts marshalOptions) int {
  49. v, info := getInfo(p)
  50. if info.funcs.size == nil {
  51. return 0
  52. }
  53. return info.funcs.size(v, info.tagsize, opts)
  54. },
  55. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  56. v, info := getInfo(p)
  57. if info.funcs.marshal == nil {
  58. return b, nil
  59. }
  60. return info.funcs.marshal(b, v, info.wiretag, opts)
  61. },
  62. isInit: func(p pointer) error {
  63. v, info := getInfo(p)
  64. if info.funcs.isInit == nil {
  65. return nil
  66. }
  67. return info.funcs.isInit(v)
  68. },
  69. }
  70. }
  71. func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
  72. if fi, ok := getMessageInfo(ft); ok {
  73. return pointerCoderFuncs{
  74. size: func(p pointer, tagsize int, opts marshalOptions) int {
  75. return sizeMessageInfo(p, fi, tagsize, opts)
  76. },
  77. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  78. return appendMessageInfo(b, p, wiretag, fi, opts)
  79. },
  80. isInit: func(p pointer) error {
  81. return fi.isInitializedPointer(p.Elem())
  82. },
  83. }
  84. } else {
  85. return pointerCoderFuncs{
  86. size: func(p pointer, tagsize int, opts marshalOptions) int {
  87. m := asMessage(p.AsValueOf(ft).Elem())
  88. return sizeMessage(m, tagsize, opts)
  89. },
  90. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  91. m := asMessage(p.AsValueOf(ft).Elem())
  92. return appendMessage(b, m, wiretag, opts)
  93. },
  94. isInit: func(p pointer) error {
  95. m := asMessage(p.AsValueOf(ft).Elem())
  96. return proto.IsInitialized(m)
  97. },
  98. }
  99. }
  100. }
  101. func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
  102. return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
  103. }
  104. func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
  105. b = wire.AppendVarint(b, wiretag)
  106. b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
  107. return mi.marshalAppendPointer(b, p.Elem(), opts)
  108. }
  109. func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
  110. return wire.SizeBytes(proto.Size(m)) + tagsize
  111. }
  112. func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
  113. b = wire.AppendVarint(b, wiretag)
  114. b = wire.AppendVarint(b, uint64(proto.Size(m)))
  115. return opts.Options().MarshalAppend(b, m)
  116. }
  117. func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
  118. m := Export{}.MessageOf(ival).Interface()
  119. return sizeMessage(m, tagsize, opts)
  120. }
  121. func appendMessageIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
  122. m := Export{}.MessageOf(ival).Interface()
  123. return appendMessage(b, m, wiretag, opts)
  124. }
  125. func isInitMessageIface(ival interface{}) error {
  126. m := Export{}.MessageOf(ival).Interface()
  127. return proto.IsInitialized(m)
  128. }
  129. var coderMessageIface = ifaceCoderFuncs{
  130. size: sizeMessageIface,
  131. marshal: appendMessageIface,
  132. isInit: isInitMessageIface,
  133. }
  134. func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
  135. if fi, ok := getMessageInfo(ft); ok {
  136. return pointerCoderFuncs{
  137. size: func(p pointer, tagsize int, opts marshalOptions) int {
  138. return sizeGroupType(p, fi, tagsize, opts)
  139. },
  140. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  141. return appendGroupType(b, p, wiretag, fi, opts)
  142. },
  143. isInit: func(p pointer) error {
  144. return fi.isInitializedPointer(p.Elem())
  145. },
  146. }
  147. } else {
  148. return pointerCoderFuncs{
  149. size: func(p pointer, tagsize int, opts marshalOptions) int {
  150. m := asMessage(p.AsValueOf(ft).Elem())
  151. return sizeGroup(m, tagsize, opts)
  152. },
  153. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  154. m := asMessage(p.AsValueOf(ft).Elem())
  155. return appendGroup(b, m, wiretag, opts)
  156. },
  157. isInit: func(p pointer) error {
  158. m := asMessage(p.AsValueOf(ft).Elem())
  159. return proto.IsInitialized(m)
  160. },
  161. }
  162. }
  163. }
  164. func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
  165. return 2*tagsize + mi.sizePointer(p.Elem(), opts)
  166. }
  167. func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
  168. b = wire.AppendVarint(b, wiretag) // start group
  169. b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
  170. b = wire.AppendVarint(b, wiretag+1) // end group
  171. return b, err
  172. }
  173. func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
  174. return 2*tagsize + proto.Size(m)
  175. }
  176. func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) {
  177. b = wire.AppendVarint(b, wiretag) // start group
  178. b, err := opts.Options().MarshalAppend(b, m)
  179. b = wire.AppendVarint(b, wiretag+1) // end group
  180. return b, err
  181. }
  182. func sizeGroupIface(ival interface{}, tagsize int, opts marshalOptions) int {
  183. m := Export{}.MessageOf(ival).Interface()
  184. return sizeGroup(m, tagsize, opts)
  185. }
  186. func appendGroupIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
  187. m := Export{}.MessageOf(ival).Interface()
  188. return appendGroup(b, m, wiretag, opts)
  189. }
  190. var coderGroupIface = ifaceCoderFuncs{
  191. size: sizeGroupIface,
  192. marshal: appendGroupIface,
  193. isInit: isInitMessageIface,
  194. }
  195. func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
  196. if fi, ok := getMessageInfo(ft); ok {
  197. return pointerCoderFuncs{
  198. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  199. return appendMessageSliceInfo(b, p, wiretag, fi, opts)
  200. },
  201. size: func(p pointer, tagsize int, opts marshalOptions) int {
  202. return sizeMessageSliceInfo(p, fi, tagsize, opts)
  203. },
  204. isInit: func(p pointer) error {
  205. return isInitMessageSliceInfo(p, fi)
  206. },
  207. }
  208. }
  209. return pointerCoderFuncs{
  210. size: func(p pointer, tagsize int, opts marshalOptions) int {
  211. return sizeMessageSlice(p, ft, tagsize, opts)
  212. },
  213. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  214. return appendMessageSlice(b, p, wiretag, ft, opts)
  215. },
  216. isInit: func(p pointer) error {
  217. return isInitMessageSlice(p, ft)
  218. },
  219. }
  220. }
  221. func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
  222. s := p.PointerSlice()
  223. n := 0
  224. for _, v := range s {
  225. n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
  226. }
  227. return n
  228. }
  229. func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
  230. s := p.PointerSlice()
  231. var err error
  232. for _, v := range s {
  233. b = wire.AppendVarint(b, wiretag)
  234. siz := mi.sizePointer(v, opts)
  235. b = wire.AppendVarint(b, uint64(siz))
  236. b, err = mi.marshalAppendPointer(b, v, opts)
  237. if err != nil {
  238. return b, err
  239. }
  240. }
  241. return b, nil
  242. }
  243. func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
  244. s := p.PointerSlice()
  245. for _, v := range s {
  246. if err := mi.isInitializedPointer(v); err != nil {
  247. return err
  248. }
  249. }
  250. return nil
  251. }
  252. func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int {
  253. s := p.PointerSlice()
  254. n := 0
  255. for _, v := range s {
  256. m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
  257. n += wire.SizeBytes(proto.Size(m)) + tagsize
  258. }
  259. return n
  260. }
  261. func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) {
  262. s := p.PointerSlice()
  263. var err error
  264. for _, v := range s {
  265. m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
  266. b = wire.AppendVarint(b, wiretag)
  267. siz := proto.Size(m)
  268. b = wire.AppendVarint(b, uint64(siz))
  269. b, err = opts.Options().MarshalAppend(b, m)
  270. if err != nil {
  271. return b, err
  272. }
  273. }
  274. return b, nil
  275. }
  276. func isInitMessageSlice(p pointer, goType reflect.Type) error {
  277. s := p.PointerSlice()
  278. for _, v := range s {
  279. m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
  280. if err := proto.IsInitialized(m); err != nil {
  281. return err
  282. }
  283. }
  284. return nil
  285. }
  286. // Slices of messages
  287. func sizeMessageSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
  288. p := pointerOfIface(ival)
  289. return sizeMessageSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
  290. }
  291. func appendMessageSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
  292. p := pointerOfIface(ival)
  293. return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
  294. }
  295. func isInitMessageSliceIface(ival interface{}) error {
  296. p := pointerOfIface(ival)
  297. return isInitMessageSlice(p, reflect.TypeOf(ival).Elem().Elem())
  298. }
  299. var coderMessageSliceIface = ifaceCoderFuncs{
  300. size: sizeMessageSliceIface,
  301. marshal: appendMessageSliceIface,
  302. isInit: isInitMessageSliceIface,
  303. }
  304. func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
  305. if fi, ok := getMessageInfo(ft); ok {
  306. return pointerCoderFuncs{
  307. size: func(p pointer, tagsize int, opts marshalOptions) int {
  308. return sizeGroupSliceInfo(p, fi, tagsize, opts)
  309. },
  310. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  311. return appendGroupSliceInfo(b, p, wiretag, fi, opts)
  312. },
  313. isInit: func(p pointer) error {
  314. return isInitMessageSliceInfo(p, fi)
  315. },
  316. }
  317. }
  318. return pointerCoderFuncs{
  319. size: func(p pointer, tagsize int, opts marshalOptions) int {
  320. return sizeGroupSlice(p, ft, tagsize, opts)
  321. },
  322. marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
  323. return appendGroupSlice(b, p, wiretag, ft, opts)
  324. },
  325. isInit: func(p pointer) error {
  326. return isInitMessageSlice(p, ft)
  327. },
  328. }
  329. }
  330. func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int {
  331. s := p.PointerSlice()
  332. n := 0
  333. for _, v := range s {
  334. m := Export{}.MessageOf(v.AsValueOf(messageType.Elem()).Interface()).Interface()
  335. n += 2*tagsize + proto.Size(m)
  336. }
  337. return n
  338. }
  339. func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) {
  340. s := p.PointerSlice()
  341. var err error
  342. for _, v := range s {
  343. m := Export{}.MessageOf(v.AsValueOf(messageType.Elem()).Interface()).Interface()
  344. b = wire.AppendVarint(b, wiretag) // start group
  345. b, err = opts.Options().MarshalAppend(b, m)
  346. if err != nil {
  347. return b, err
  348. }
  349. b = wire.AppendVarint(b, wiretag+1) // end group
  350. }
  351. return b, nil
  352. }
  353. func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
  354. s := p.PointerSlice()
  355. n := 0
  356. for _, v := range s {
  357. n += 2*tagsize + mi.sizePointer(v, opts)
  358. }
  359. return n
  360. }
  361. func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
  362. s := p.PointerSlice()
  363. var err error
  364. for _, v := range s {
  365. b = wire.AppendVarint(b, wiretag) // start group
  366. b, err = mi.marshalAppendPointer(b, v, opts)
  367. if err != nil {
  368. return b, err
  369. }
  370. b = wire.AppendVarint(b, wiretag+1) // end group
  371. }
  372. return b, nil
  373. }
  374. func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
  375. p := pointerOfIface(ival)
  376. return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
  377. }
  378. func appendGroupSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
  379. p := pointerOfIface(ival)
  380. return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
  381. }
  382. var coderGroupSliceIface = ifaceCoderFuncs{
  383. size: sizeGroupSliceIface,
  384. marshal: appendGroupSliceIface,
  385. isInit: isInitMessageSliceIface,
  386. }
  387. // Enums
  388. func sizeEnumIface(ival interface{}, tagsize int, _ marshalOptions) (n int) {
  389. v := reflect.ValueOf(ival).Int()
  390. return wire.SizeVarint(uint64(v)) + tagsize
  391. }
  392. func appendEnumIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
  393. v := reflect.ValueOf(ival).Int()
  394. b = wire.AppendVarint(b, wiretag)
  395. b = wire.AppendVarint(b, uint64(v))
  396. return b, nil
  397. }
  398. var coderEnumIface = ifaceCoderFuncs{
  399. size: sizeEnumIface,
  400. marshal: appendEnumIface,
  401. }
  402. func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
  403. return sizeEnumSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
  404. }
  405. func sizeEnumSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
  406. for i, llen := 0, s.Len(); i < llen; i++ {
  407. size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
  408. }
  409. return size
  410. }
  411. func appendEnumSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
  412. return appendEnumSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
  413. }
  414. func appendEnumSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
  415. for i, llen := 0, s.Len(); i < llen; i++ {
  416. b = wire.AppendVarint(b, wiretag)
  417. b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
  418. }
  419. return b, nil
  420. }
  421. var coderEnumSliceIface = ifaceCoderFuncs{
  422. size: sizeEnumSliceIface,
  423. marshal: appendEnumSliceIface,
  424. }
  425. // Strings with UTF8 validation.
  426. func appendStringValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
  427. v := *p.String()
  428. b = wire.AppendVarint(b, wiretag)
  429. b = wire.AppendString(b, v)
  430. if !utf8.ValidString(v) {
  431. return b, errInvalidUTF8{}
  432. }
  433. return b, nil
  434. }
  435. var coderStringValidateUTF8 = pointerCoderFuncs{
  436. size: sizeString,
  437. marshal: appendStringValidateUTF8,
  438. }
  439. func appendStringNoZeroValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
  440. v := *p.String()
  441. if len(v) == 0 {
  442. return b, nil
  443. }
  444. b = wire.AppendVarint(b, wiretag)
  445. b = wire.AppendString(b, v)
  446. if !utf8.ValidString(v) {
  447. return b, errInvalidUTF8{}
  448. }
  449. return b, nil
  450. }
  451. var coderStringNoZeroValidateUTF8 = pointerCoderFuncs{
  452. size: sizeStringNoZero,
  453. marshal: appendStringNoZeroValidateUTF8,
  454. }
  455. func sizeStringSliceValidateUTF8(p pointer, tagsize int, _ marshalOptions) (size int) {
  456. s := *p.StringSlice()
  457. for _, v := range s {
  458. size += tagsize + wire.SizeBytes(len(v))
  459. }
  460. return size
  461. }
  462. func appendStringSliceValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
  463. s := *p.StringSlice()
  464. var err error
  465. for _, v := range s {
  466. b = wire.AppendVarint(b, wiretag)
  467. b = wire.AppendString(b, v)
  468. if !utf8.ValidString(v) {
  469. err = errInvalidUTF8{}
  470. }
  471. }
  472. return b, err
  473. }
  474. var coderStringSliceValidateUTF8 = pointerCoderFuncs{
  475. size: sizeStringSliceValidateUTF8,
  476. marshal: appendStringSliceValidateUTF8,
  477. }
  478. func sizeStringIfaceValidateUTF8(ival interface{}, tagsize int, _ marshalOptions) int {
  479. v := ival.(string)
  480. return tagsize + wire.SizeBytes(len(v))
  481. }
  482. func appendStringIfaceValidateUTF8(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
  483. v := ival.(string)
  484. b = wire.AppendVarint(b, wiretag)
  485. b = wire.AppendString(b, v)
  486. if !utf8.ValidString(v) {
  487. return b, errInvalidUTF8{}
  488. }
  489. return b, nil
  490. }
  491. var coderStringIfaceValidateUTF8 = ifaceCoderFuncs{
  492. size: sizeStringIfaceValidateUTF8,
  493. marshal: appendStringIfaceValidateUTF8,
  494. }
  495. func asMessage(v reflect.Value) pref.ProtoMessage {
  496. if m, ok := v.Interface().(pref.ProtoMessage); ok {
  497. return m
  498. }
  499. return legacyWrapMessage(v)
  500. }