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