blob: 72924a9050cfbf4441b5ef499a69ed6088307425 [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001// 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
5package protojson
6
7import (
8 "bytes"
9 "fmt"
10 "math"
11 "strconv"
12 "strings"
13 "time"
14
15 "google.golang.org/protobuf/internal/encoding/json"
16 "google.golang.org/protobuf/internal/errors"
17 "google.golang.org/protobuf/internal/genid"
18 "google.golang.org/protobuf/internal/strs"
19 "google.golang.org/protobuf/proto"
20 pref "google.golang.org/protobuf/reflect/protoreflect"
21)
22
23type marshalFunc func(encoder, pref.Message) error
24
25// wellKnownTypeMarshaler returns a marshal function if the message type
26// has specialized serialization behavior. It returns nil otherwise.
27func wellKnownTypeMarshaler(name pref.FullName) marshalFunc {
28 if name.Parent() == genid.GoogleProtobuf_package {
29 switch name.Name() {
30 case genid.Any_message_name:
31 return encoder.marshalAny
32 case genid.Timestamp_message_name:
33 return encoder.marshalTimestamp
34 case genid.Duration_message_name:
35 return encoder.marshalDuration
36 case genid.BoolValue_message_name,
37 genid.Int32Value_message_name,
38 genid.Int64Value_message_name,
39 genid.UInt32Value_message_name,
40 genid.UInt64Value_message_name,
41 genid.FloatValue_message_name,
42 genid.DoubleValue_message_name,
43 genid.StringValue_message_name,
44 genid.BytesValue_message_name:
45 return encoder.marshalWrapperType
46 case genid.Struct_message_name:
47 return encoder.marshalStruct
48 case genid.ListValue_message_name:
49 return encoder.marshalListValue
50 case genid.Value_message_name:
51 return encoder.marshalKnownValue
52 case genid.FieldMask_message_name:
53 return encoder.marshalFieldMask
54 case genid.Empty_message_name:
55 return encoder.marshalEmpty
56 }
57 }
58 return nil
59}
60
61type unmarshalFunc func(decoder, pref.Message) error
62
63// wellKnownTypeUnmarshaler returns a unmarshal function if the message type
64// has specialized serialization behavior. It returns nil otherwise.
65func wellKnownTypeUnmarshaler(name pref.FullName) unmarshalFunc {
66 if name.Parent() == genid.GoogleProtobuf_package {
67 switch name.Name() {
68 case genid.Any_message_name:
69 return decoder.unmarshalAny
70 case genid.Timestamp_message_name:
71 return decoder.unmarshalTimestamp
72 case genid.Duration_message_name:
73 return decoder.unmarshalDuration
74 case genid.BoolValue_message_name,
75 genid.Int32Value_message_name,
76 genid.Int64Value_message_name,
77 genid.UInt32Value_message_name,
78 genid.UInt64Value_message_name,
79 genid.FloatValue_message_name,
80 genid.DoubleValue_message_name,
81 genid.StringValue_message_name,
82 genid.BytesValue_message_name:
83 return decoder.unmarshalWrapperType
84 case genid.Struct_message_name:
85 return decoder.unmarshalStruct
86 case genid.ListValue_message_name:
87 return decoder.unmarshalListValue
88 case genid.Value_message_name:
89 return decoder.unmarshalKnownValue
90 case genid.FieldMask_message_name:
91 return decoder.unmarshalFieldMask
92 case genid.Empty_message_name:
93 return decoder.unmarshalEmpty
94 }
95 }
96 return nil
97}
98
99// The JSON representation of an Any message uses the regular representation of
100// the deserialized, embedded message, with an additional field `@type` which
101// contains the type URL. If the embedded message type is well-known and has a
102// custom JSON representation, that representation will be embedded adding a
103// field `value` which holds the custom JSON in addition to the `@type` field.
104
105func (e encoder) marshalAny(m pref.Message) error {
106 fds := m.Descriptor().Fields()
107 fdType := fds.ByNumber(genid.Any_TypeUrl_field_number)
108 fdValue := fds.ByNumber(genid.Any_Value_field_number)
109
110 if !m.Has(fdType) {
111 if !m.Has(fdValue) {
112 // If message is empty, marshal out empty JSON object.
113 e.StartObject()
114 e.EndObject()
115 return nil
116 } else {
117 // Return error if type_url field is not set, but value is set.
118 return errors.New("%s: %v is not set", genid.Any_message_fullname, genid.Any_TypeUrl_field_name)
119 }
120 }
121
122 typeVal := m.Get(fdType)
123 valueVal := m.Get(fdValue)
124
125 // Resolve the type in order to unmarshal value field.
126 typeURL := typeVal.String()
127 emt, err := e.opts.Resolver.FindMessageByURL(typeURL)
128 if err != nil {
129 return errors.New("%s: unable to resolve %q: %v", genid.Any_message_fullname, typeURL, err)
130 }
131
132 em := emt.New()
133 err = proto.UnmarshalOptions{
134 AllowPartial: true, // never check required fields inside an Any
135 Resolver: e.opts.Resolver,
136 }.Unmarshal(valueVal.Bytes(), em.Interface())
137 if err != nil {
138 return errors.New("%s: unable to unmarshal %q: %v", genid.Any_message_fullname, typeURL, err)
139 }
140
141 // If type of value has custom JSON encoding, marshal out a field "value"
142 // with corresponding custom JSON encoding of the embedded message as a
143 // field.
144 if marshal := wellKnownTypeMarshaler(emt.Descriptor().FullName()); marshal != nil {
145 e.StartObject()
146 defer e.EndObject()
147
148 // Marshal out @type field.
149 e.WriteName("@type")
150 if err := e.WriteString(typeURL); err != nil {
151 return err
152 }
153
154 e.WriteName("value")
155 return marshal(e, em)
156 }
157
158 // Else, marshal out the embedded message's fields in this Any object.
159 if err := e.marshalMessage(em, typeURL); err != nil {
160 return err
161 }
162
163 return nil
164}
165
166func (d decoder) unmarshalAny(m pref.Message) error {
167 // Peek to check for json.ObjectOpen to avoid advancing a read.
168 start, err := d.Peek()
169 if err != nil {
170 return err
171 }
172 if start.Kind() != json.ObjectOpen {
173 return d.unexpectedTokenError(start)
174 }
175
176 // Use another decoder to parse the unread bytes for @type field. This
177 // avoids advancing a read from current decoder because the current JSON
178 // object may contain the fields of the embedded type.
179 dec := decoder{d.Clone(), UnmarshalOptions{}}
180 tok, err := findTypeURL(dec)
181 switch err {
182 case errEmptyObject:
183 // An empty JSON object translates to an empty Any message.
184 d.Read() // Read json.ObjectOpen.
185 d.Read() // Read json.ObjectClose.
186 return nil
187
188 case errMissingType:
189 if d.opts.DiscardUnknown {
190 // Treat all fields as unknowns, similar to an empty object.
191 return d.skipJSONValue()
192 }
193 // Use start.Pos() for line position.
194 return d.newError(start.Pos(), err.Error())
195
196 default:
197 if err != nil {
198 return err
199 }
200 }
201
202 typeURL := tok.ParsedString()
203 emt, err := d.opts.Resolver.FindMessageByURL(typeURL)
204 if err != nil {
205 return d.newError(tok.Pos(), "unable to resolve %v: %q", tok.RawString(), err)
206 }
207
208 // Create new message for the embedded message type and unmarshal into it.
209 em := emt.New()
210 if unmarshal := wellKnownTypeUnmarshaler(emt.Descriptor().FullName()); unmarshal != nil {
211 // If embedded message is a custom type,
212 // unmarshal the JSON "value" field into it.
213 if err := d.unmarshalAnyValue(unmarshal, em); err != nil {
214 return err
215 }
216 } else {
217 // Else unmarshal the current JSON object into it.
218 if err := d.unmarshalMessage(em, true); err != nil {
219 return err
220 }
221 }
222 // Serialize the embedded message and assign the resulting bytes to the
223 // proto value field.
224 b, err := proto.MarshalOptions{
225 AllowPartial: true, // No need to check required fields inside an Any.
226 Deterministic: true,
227 }.Marshal(em.Interface())
228 if err != nil {
229 return d.newError(start.Pos(), "error in marshaling Any.value field: %v", err)
230 }
231
232 fds := m.Descriptor().Fields()
233 fdType := fds.ByNumber(genid.Any_TypeUrl_field_number)
234 fdValue := fds.ByNumber(genid.Any_Value_field_number)
235
236 m.Set(fdType, pref.ValueOfString(typeURL))
237 m.Set(fdValue, pref.ValueOfBytes(b))
238 return nil
239}
240
241var errEmptyObject = fmt.Errorf(`empty object`)
242var errMissingType = fmt.Errorf(`missing "@type" field`)
243
244// findTypeURL returns the token for the "@type" field value from the given
245// JSON bytes. It is expected that the given bytes start with json.ObjectOpen.
246// It returns errEmptyObject if the JSON object is empty or errMissingType if
247// @type field does not exist. It returns other error if the @type field is not
248// valid or other decoding issues.
249func findTypeURL(d decoder) (json.Token, error) {
250 var typeURL string
251 var typeTok json.Token
252 numFields := 0
253 // Skip start object.
254 d.Read()
255
256Loop:
257 for {
258 tok, err := d.Read()
259 if err != nil {
260 return json.Token{}, err
261 }
262
263 switch tok.Kind() {
264 case json.ObjectClose:
265 if typeURL == "" {
266 // Did not find @type field.
267 if numFields > 0 {
268 return json.Token{}, errMissingType
269 }
270 return json.Token{}, errEmptyObject
271 }
272 break Loop
273
274 case json.Name:
275 numFields++
276 if tok.Name() != "@type" {
277 // Skip value.
278 if err := d.skipJSONValue(); err != nil {
279 return json.Token{}, err
280 }
281 continue
282 }
283
284 // Return error if this was previously set already.
285 if typeURL != "" {
286 return json.Token{}, d.newError(tok.Pos(), `duplicate "@type" field`)
287 }
288 // Read field value.
289 tok, err := d.Read()
290 if err != nil {
291 return json.Token{}, err
292 }
293 if tok.Kind() != json.String {
294 return json.Token{}, d.newError(tok.Pos(), `@type field value is not a string: %v`, tok.RawString())
295 }
296 typeURL = tok.ParsedString()
297 if typeURL == "" {
298 return json.Token{}, d.newError(tok.Pos(), `@type field contains empty value`)
299 }
300 typeTok = tok
301 }
302 }
303
304 return typeTok, nil
305}
306
307// skipJSONValue parses a JSON value (null, boolean, string, number, object and
308// array) in order to advance the read to the next JSON value. It relies on
309// the decoder returning an error if the types are not in valid sequence.
310func (d decoder) skipJSONValue() error {
311 tok, err := d.Read()
312 if err != nil {
313 return err
314 }
315 // Only need to continue reading for objects and arrays.
316 switch tok.Kind() {
317 case json.ObjectOpen:
318 for {
319 tok, err := d.Read()
320 if err != nil {
321 return err
322 }
323 switch tok.Kind() {
324 case json.ObjectClose:
325 return nil
326 case json.Name:
327 // Skip object field value.
328 if err := d.skipJSONValue(); err != nil {
329 return err
330 }
331 }
332 }
333
334 case json.ArrayOpen:
335 for {
336 tok, err := d.Peek()
337 if err != nil {
338 return err
339 }
340 switch tok.Kind() {
341 case json.ArrayClose:
342 d.Read()
343 return nil
344 default:
345 // Skip array item.
346 if err := d.skipJSONValue(); err != nil {
347 return err
348 }
349 }
350 }
351 }
352 return nil
353}
354
355// unmarshalAnyValue unmarshals the given custom-type message from the JSON
356// object's "value" field.
357func (d decoder) unmarshalAnyValue(unmarshal unmarshalFunc, m pref.Message) error {
358 // Skip ObjectOpen, and start reading the fields.
359 d.Read()
360
361 var found bool // Used for detecting duplicate "value".
362 for {
363 tok, err := d.Read()
364 if err != nil {
365 return err
366 }
367 switch tok.Kind() {
368 case json.ObjectClose:
369 if !found {
370 return d.newError(tok.Pos(), `missing "value" field`)
371 }
372 return nil
373
374 case json.Name:
375 switch tok.Name() {
376 case "@type":
377 // Skip the value as this was previously parsed already.
378 d.Read()
379
380 case "value":
381 if found {
382 return d.newError(tok.Pos(), `duplicate "value" field`)
383 }
384 // Unmarshal the field value into the given message.
385 if err := unmarshal(d, m); err != nil {
386 return err
387 }
388 found = true
389
390 default:
391 if d.opts.DiscardUnknown {
392 if err := d.skipJSONValue(); err != nil {
393 return err
394 }
395 continue
396 }
397 return d.newError(tok.Pos(), "unknown field %v", tok.RawString())
398 }
399 }
400 }
401}
402
403// Wrapper types are encoded as JSON primitives like string, number or boolean.
404
405func (e encoder) marshalWrapperType(m pref.Message) error {
406 fd := m.Descriptor().Fields().ByNumber(genid.WrapperValue_Value_field_number)
407 val := m.Get(fd)
408 return e.marshalSingular(val, fd)
409}
410
411func (d decoder) unmarshalWrapperType(m pref.Message) error {
412 fd := m.Descriptor().Fields().ByNumber(genid.WrapperValue_Value_field_number)
413 val, err := d.unmarshalScalar(fd)
414 if err != nil {
415 return err
416 }
417 m.Set(fd, val)
418 return nil
419}
420
421// The JSON representation for Empty is an empty JSON object.
422
423func (e encoder) marshalEmpty(pref.Message) error {
424 e.StartObject()
425 e.EndObject()
426 return nil
427}
428
429func (d decoder) unmarshalEmpty(pref.Message) error {
430 tok, err := d.Read()
431 if err != nil {
432 return err
433 }
434 if tok.Kind() != json.ObjectOpen {
435 return d.unexpectedTokenError(tok)
436 }
437
438 for {
439 tok, err := d.Read()
440 if err != nil {
441 return err
442 }
443 switch tok.Kind() {
444 case json.ObjectClose:
445 return nil
446
447 case json.Name:
448 if d.opts.DiscardUnknown {
449 if err := d.skipJSONValue(); err != nil {
450 return err
451 }
452 continue
453 }
454 return d.newError(tok.Pos(), "unknown field %v", tok.RawString())
455
456 default:
457 return d.unexpectedTokenError(tok)
458 }
459 }
460}
461
462// The JSON representation for Struct is a JSON object that contains the encoded
463// Struct.fields map and follows the serialization rules for a map.
464
465func (e encoder) marshalStruct(m pref.Message) error {
466 fd := m.Descriptor().Fields().ByNumber(genid.Struct_Fields_field_number)
467 return e.marshalMap(m.Get(fd).Map(), fd)
468}
469
470func (d decoder) unmarshalStruct(m pref.Message) error {
471 fd := m.Descriptor().Fields().ByNumber(genid.Struct_Fields_field_number)
472 return d.unmarshalMap(m.Mutable(fd).Map(), fd)
473}
474
475// The JSON representation for ListValue is JSON array that contains the encoded
476// ListValue.values repeated field and follows the serialization rules for a
477// repeated field.
478
479func (e encoder) marshalListValue(m pref.Message) error {
480 fd := m.Descriptor().Fields().ByNumber(genid.ListValue_Values_field_number)
481 return e.marshalList(m.Get(fd).List(), fd)
482}
483
484func (d decoder) unmarshalListValue(m pref.Message) error {
485 fd := m.Descriptor().Fields().ByNumber(genid.ListValue_Values_field_number)
486 return d.unmarshalList(m.Mutable(fd).List(), fd)
487}
488
489// The JSON representation for a Value is dependent on the oneof field that is
490// set. Each of the field in the oneof has its own custom serialization rule. A
491// Value message needs to be a oneof field set, else it is an error.
492
493func (e encoder) marshalKnownValue(m pref.Message) error {
494 od := m.Descriptor().Oneofs().ByName(genid.Value_Kind_oneof_name)
495 fd := m.WhichOneof(od)
496 if fd == nil {
497 return errors.New("%s: none of the oneof fields is set", genid.Value_message_fullname)
498 }
499 if fd.Number() == genid.Value_NumberValue_field_number {
500 if v := m.Get(fd).Float(); math.IsNaN(v) || math.IsInf(v, 0) {
501 return errors.New("%s: invalid %v value", genid.Value_NumberValue_field_fullname, v)
502 }
503 }
504 return e.marshalSingular(m.Get(fd), fd)
505}
506
507func (d decoder) unmarshalKnownValue(m pref.Message) error {
508 tok, err := d.Peek()
509 if err != nil {
510 return err
511 }
512
513 var fd pref.FieldDescriptor
514 var val pref.Value
515 switch tok.Kind() {
516 case json.Null:
517 d.Read()
518 fd = m.Descriptor().Fields().ByNumber(genid.Value_NullValue_field_number)
519 val = pref.ValueOfEnum(0)
520
521 case json.Bool:
522 tok, err := d.Read()
523 if err != nil {
524 return err
525 }
526 fd = m.Descriptor().Fields().ByNumber(genid.Value_BoolValue_field_number)
527 val = pref.ValueOfBool(tok.Bool())
528
529 case json.Number:
530 tok, err := d.Read()
531 if err != nil {
532 return err
533 }
534 fd = m.Descriptor().Fields().ByNumber(genid.Value_NumberValue_field_number)
535 var ok bool
536 val, ok = unmarshalFloat(tok, 64)
537 if !ok {
538 return d.newError(tok.Pos(), "invalid %v: %v", genid.Value_message_fullname, tok.RawString())
539 }
540
541 case json.String:
542 // A JSON string may have been encoded from the number_value field,
543 // e.g. "NaN", "Infinity", etc. Parsing a proto double type also allows
544 // for it to be in JSON string form. Given this custom encoding spec,
545 // however, there is no way to identify that and hence a JSON string is
546 // always assigned to the string_value field, which means that certain
547 // encoding cannot be parsed back to the same field.
548 tok, err := d.Read()
549 if err != nil {
550 return err
551 }
552 fd = m.Descriptor().Fields().ByNumber(genid.Value_StringValue_field_number)
553 val = pref.ValueOfString(tok.ParsedString())
554
555 case json.ObjectOpen:
556 fd = m.Descriptor().Fields().ByNumber(genid.Value_StructValue_field_number)
557 val = m.NewField(fd)
558 if err := d.unmarshalStruct(val.Message()); err != nil {
559 return err
560 }
561
562 case json.ArrayOpen:
563 fd = m.Descriptor().Fields().ByNumber(genid.Value_ListValue_field_number)
564 val = m.NewField(fd)
565 if err := d.unmarshalListValue(val.Message()); err != nil {
566 return err
567 }
568
569 default:
570 return d.newError(tok.Pos(), "invalid %v: %v", genid.Value_message_fullname, tok.RawString())
571 }
572
573 m.Set(fd, val)
574 return nil
575}
576
577// The JSON representation for a Duration is a JSON string that ends in the
578// suffix "s" (indicating seconds) and is preceded by the number of seconds,
579// with nanoseconds expressed as fractional seconds.
580//
581// Durations less than one second are represented with a 0 seconds field and a
582// positive or negative nanos field. For durations of one second or more, a
583// non-zero value for the nanos field must be of the same sign as the seconds
584// field.
585//
586// Duration.seconds must be from -315,576,000,000 to +315,576,000,000 inclusive.
587// Duration.nanos must be from -999,999,999 to +999,999,999 inclusive.
588
589const (
590 secondsInNanos = 999999999
591 maxSecondsInDuration = 315576000000
592)
593
594func (e encoder) marshalDuration(m pref.Message) error {
595 fds := m.Descriptor().Fields()
596 fdSeconds := fds.ByNumber(genid.Duration_Seconds_field_number)
597 fdNanos := fds.ByNumber(genid.Duration_Nanos_field_number)
598
599 secsVal := m.Get(fdSeconds)
600 nanosVal := m.Get(fdNanos)
601 secs := secsVal.Int()
602 nanos := nanosVal.Int()
603 if secs < -maxSecondsInDuration || secs > maxSecondsInDuration {
604 return errors.New("%s: seconds out of range %v", genid.Duration_message_fullname, secs)
605 }
606 if nanos < -secondsInNanos || nanos > secondsInNanos {
607 return errors.New("%s: nanos out of range %v", genid.Duration_message_fullname, nanos)
608 }
609 if (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0) {
610 return errors.New("%s: signs of seconds and nanos do not match", genid.Duration_message_fullname)
611 }
612 // Generated output always contains 0, 3, 6, or 9 fractional digits,
613 // depending on required precision, followed by the suffix "s".
614 var sign string
615 if secs < 0 || nanos < 0 {
616 sign, secs, nanos = "-", -1*secs, -1*nanos
617 }
618 x := fmt.Sprintf("%s%d.%09d", sign, secs, nanos)
619 x = strings.TrimSuffix(x, "000")
620 x = strings.TrimSuffix(x, "000")
621 x = strings.TrimSuffix(x, ".000")
622 e.WriteString(x + "s")
623 return nil
624}
625
626func (d decoder) unmarshalDuration(m pref.Message) error {
627 tok, err := d.Read()
628 if err != nil {
629 return err
630 }
631 if tok.Kind() != json.String {
632 return d.unexpectedTokenError(tok)
633 }
634
635 secs, nanos, ok := parseDuration(tok.ParsedString())
636 if !ok {
637 return d.newError(tok.Pos(), "invalid %v value %v", genid.Duration_message_fullname, tok.RawString())
638 }
639 // Validate seconds. No need to validate nanos because parseDuration would
640 // have covered that already.
641 if secs < -maxSecondsInDuration || secs > maxSecondsInDuration {
642 return d.newError(tok.Pos(), "%v value out of range: %v", genid.Duration_message_fullname, tok.RawString())
643 }
644
645 fds := m.Descriptor().Fields()
646 fdSeconds := fds.ByNumber(genid.Duration_Seconds_field_number)
647 fdNanos := fds.ByNumber(genid.Duration_Nanos_field_number)
648
649 m.Set(fdSeconds, pref.ValueOfInt64(secs))
650 m.Set(fdNanos, pref.ValueOfInt32(nanos))
651 return nil
652}
653
654// parseDuration parses the given input string for seconds and nanoseconds value
655// for the Duration JSON format. The format is a decimal number with a suffix
656// 's'. It can have optional plus/minus sign. There needs to be at least an
657// integer or fractional part. Fractional part is limited to 9 digits only for
658// nanoseconds precision, regardless of whether there are trailing zero digits.
659// Example values are 1s, 0.1s, 1.s, .1s, +1s, -1s, -.1s.
660func parseDuration(input string) (int64, int32, bool) {
661 b := []byte(input)
662 size := len(b)
663 if size < 2 {
664 return 0, 0, false
665 }
666 if b[size-1] != 's' {
667 return 0, 0, false
668 }
669 b = b[:size-1]
670
671 // Read optional plus/minus symbol.
672 var neg bool
673 switch b[0] {
674 case '-':
675 neg = true
676 b = b[1:]
677 case '+':
678 b = b[1:]
679 }
680 if len(b) == 0 {
681 return 0, 0, false
682 }
683
684 // Read the integer part.
685 var intp []byte
686 switch {
687 case b[0] == '0':
688 b = b[1:]
689
690 case '1' <= b[0] && b[0] <= '9':
691 intp = b[0:]
692 b = b[1:]
693 n := 1
694 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
695 n++
696 b = b[1:]
697 }
698 intp = intp[:n]
699
700 case b[0] == '.':
701 // Continue below.
702
703 default:
704 return 0, 0, false
705 }
706
707 hasFrac := false
708 var frac [9]byte
709 if len(b) > 0 {
710 if b[0] != '.' {
711 return 0, 0, false
712 }
713 // Read the fractional part.
714 b = b[1:]
715 n := 0
716 for len(b) > 0 && n < 9 && '0' <= b[0] && b[0] <= '9' {
717 frac[n] = b[0]
718 n++
719 b = b[1:]
720 }
721 // It is not valid if there are more bytes left.
722 if len(b) > 0 {
723 return 0, 0, false
724 }
725 // Pad fractional part with 0s.
726 for i := n; i < 9; i++ {
727 frac[i] = '0'
728 }
729 hasFrac = true
730 }
731
732 var secs int64
733 if len(intp) > 0 {
734 var err error
735 secs, err = strconv.ParseInt(string(intp), 10, 64)
736 if err != nil {
737 return 0, 0, false
738 }
739 }
740
741 var nanos int64
742 if hasFrac {
743 nanob := bytes.TrimLeft(frac[:], "0")
744 if len(nanob) > 0 {
745 var err error
746 nanos, err = strconv.ParseInt(string(nanob), 10, 32)
747 if err != nil {
748 return 0, 0, false
749 }
750 }
751 }
752
753 if neg {
754 if secs > 0 {
755 secs = -secs
756 }
757 if nanos > 0 {
758 nanos = -nanos
759 }
760 }
761 return secs, int32(nanos), true
762}
763
764// The JSON representation for a Timestamp is a JSON string in the RFC 3339
765// format, i.e. "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" where
766// {year} is always expressed using four digits while {month}, {day}, {hour},
767// {min}, and {sec} are zero-padded to two digits each. The fractional seconds,
768// which can go up to 9 digits, up to 1 nanosecond resolution, is optional. The
769// "Z" suffix indicates the timezone ("UTC"); the timezone is required. Encoding
770// should always use UTC (as indicated by "Z") and a decoder should be able to
771// accept both UTC and other timezones (as indicated by an offset).
772//
773// Timestamp.seconds must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z
774// inclusive.
775// Timestamp.nanos must be from 0 to 999,999,999 inclusive.
776
777const (
778 maxTimestampSeconds = 253402300799
779 minTimestampSeconds = -62135596800
780)
781
782func (e encoder) marshalTimestamp(m pref.Message) error {
783 fds := m.Descriptor().Fields()
784 fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number)
785 fdNanos := fds.ByNumber(genid.Timestamp_Nanos_field_number)
786
787 secsVal := m.Get(fdSeconds)
788 nanosVal := m.Get(fdNanos)
789 secs := secsVal.Int()
790 nanos := nanosVal.Int()
791 if secs < minTimestampSeconds || secs > maxTimestampSeconds {
792 return errors.New("%s: seconds out of range %v", genid.Timestamp_message_fullname, secs)
793 }
794 if nanos < 0 || nanos > secondsInNanos {
795 return errors.New("%s: nanos out of range %v", genid.Timestamp_message_fullname, nanos)
796 }
797 // Uses RFC 3339, where generated output will be Z-normalized and uses 0, 3,
798 // 6 or 9 fractional digits.
799 t := time.Unix(secs, nanos).UTC()
800 x := t.Format("2006-01-02T15:04:05.000000000")
801 x = strings.TrimSuffix(x, "000")
802 x = strings.TrimSuffix(x, "000")
803 x = strings.TrimSuffix(x, ".000")
804 e.WriteString(x + "Z")
805 return nil
806}
807
808func (d decoder) unmarshalTimestamp(m pref.Message) error {
809 tok, err := d.Read()
810 if err != nil {
811 return err
812 }
813 if tok.Kind() != json.String {
814 return d.unexpectedTokenError(tok)
815 }
816
817 t, err := time.Parse(time.RFC3339Nano, tok.ParsedString())
818 if err != nil {
819 return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString())
820 }
821 // Validate seconds. No need to validate nanos because time.Parse would have
822 // covered that already.
823 secs := t.Unix()
824 if secs < minTimestampSeconds || secs > maxTimestampSeconds {
825 return d.newError(tok.Pos(), "%v value out of range: %v", genid.Timestamp_message_fullname, tok.RawString())
826 }
827
828 fds := m.Descriptor().Fields()
829 fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number)
830 fdNanos := fds.ByNumber(genid.Timestamp_Nanos_field_number)
831
832 m.Set(fdSeconds, pref.ValueOfInt64(secs))
833 m.Set(fdNanos, pref.ValueOfInt32(int32(t.Nanosecond())))
834 return nil
835}
836
837// The JSON representation for a FieldMask is a JSON string where paths are
838// separated by a comma. Fields name in each path are converted to/from
839// lower-camel naming conventions. Encoding should fail if the path name would
840// end up differently after a round-trip.
841
842func (e encoder) marshalFieldMask(m pref.Message) error {
843 fd := m.Descriptor().Fields().ByNumber(genid.FieldMask_Paths_field_number)
844 list := m.Get(fd).List()
845 paths := make([]string, 0, list.Len())
846
847 for i := 0; i < list.Len(); i++ {
848 s := list.Get(i).String()
849 if !pref.FullName(s).IsValid() {
850 return errors.New("%s contains invalid path: %q", genid.FieldMask_Paths_field_fullname, s)
851 }
852 // Return error if conversion to camelCase is not reversible.
853 cc := strs.JSONCamelCase(s)
854 if s != strs.JSONSnakeCase(cc) {
855 return errors.New("%s contains irreversible value %q", genid.FieldMask_Paths_field_fullname, s)
856 }
857 paths = append(paths, cc)
858 }
859
860 e.WriteString(strings.Join(paths, ","))
861 return nil
862}
863
864func (d decoder) unmarshalFieldMask(m pref.Message) error {
865 tok, err := d.Read()
866 if err != nil {
867 return err
868 }
869 if tok.Kind() != json.String {
870 return d.unexpectedTokenError(tok)
871 }
872 str := strings.TrimSpace(tok.ParsedString())
873 if str == "" {
874 return nil
875 }
876 paths := strings.Split(str, ",")
877
878 fd := m.Descriptor().Fields().ByNumber(genid.FieldMask_Paths_field_number)
879 list := m.Mutable(fd).List()
880
881 for _, s0 := range paths {
882 s := strs.JSONSnakeCase(s0)
883 if strings.Contains(s0, "_") || !pref.FullName(s).IsValid() {
884 return d.newError(tok.Pos(), "%v contains invalid path: %q", genid.FieldMask_Paths_field_fullname, s0)
885 }
886 list.Append(pref.ValueOfString(s))
887 }
888 return nil
889}