github.com/whiteCcinn/protobuf-go@v1.0.9/encoding/protojson/well_known_types.go (about)

     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  
     5  package protojson
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"math"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/whiteCcinn/protobuf-go/internal/encoding/json"
    16  	"github.com/whiteCcinn/protobuf-go/internal/errors"
    17  	"github.com/whiteCcinn/protobuf-go/internal/genid"
    18  	"github.com/whiteCcinn/protobuf-go/internal/strs"
    19  	"github.com/whiteCcinn/protobuf-go/proto"
    20  	"github.com/whiteCcinn/protobuf-go/reflect/protoreflect"
    21  )
    22  
    23  type marshalFunc func(encoder, protoreflect.Message) error
    24  
    25  // wellKnownTypeMarshaler returns a marshal function if the message type
    26  // has specialized serialization behavior. It returns nil otherwise.
    27  func wellKnownTypeMarshaler(name protoreflect.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  
    61  type unmarshalFunc func(decoder, protoreflect.Message) error
    62  
    63  // wellKnownTypeUnmarshaler returns a unmarshal function if the message type
    64  // has specialized serialization behavior. It returns nil otherwise.
    65  func wellKnownTypeUnmarshaler(name protoreflect.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  
   105  func (e encoder) marshalAny(m protoreflect.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  
   166  func (d decoder) unmarshalAny(m protoreflect.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, protoreflect.ValueOfString(typeURL))
   237  	m.Set(fdValue, protoreflect.ValueOfBytes(b))
   238  	return nil
   239  }
   240  
   241  var errEmptyObject = fmt.Errorf(`empty object`)
   242  var 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.
   249  func 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  
   256  Loop:
   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.
   310  func (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.
   357  func (d decoder) unmarshalAnyValue(unmarshal unmarshalFunc, m protoreflect.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  
   405  func (e encoder) marshalWrapperType(m protoreflect.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  
   411  func (d decoder) unmarshalWrapperType(m protoreflect.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  
   423  func (e encoder) marshalEmpty(protoreflect.Message) error {
   424  	e.StartObject()
   425  	e.EndObject()
   426  	return nil
   427  }
   428  
   429  func (d decoder) unmarshalEmpty(protoreflect.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  
   465  func (e encoder) marshalStruct(m protoreflect.Message) error {
   466  	fd := m.Descriptor().Fields().ByNumber(genid.Struct_Fields_field_number)
   467  	return e.marshalMap(m.Get(fd).Map(), fd)
   468  }
   469  
   470  func (d decoder) unmarshalStruct(m protoreflect.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  
   479  func (e encoder) marshalListValue(m protoreflect.Message) error {
   480  	fd := m.Descriptor().Fields().ByNumber(genid.ListValue_Values_field_number)
   481  	return e.marshalList(m.Get(fd).List(), fd)
   482  }
   483  
   484  func (d decoder) unmarshalListValue(m protoreflect.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  
   493  func (e encoder) marshalKnownValue(m protoreflect.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  
   507  func (d decoder) unmarshalKnownValue(m protoreflect.Message) error {
   508  	tok, err := d.Peek()
   509  	if err != nil {
   510  		return err
   511  	}
   512  
   513  	var fd protoreflect.FieldDescriptor
   514  	var val protoreflect.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 = protoreflect.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 = protoreflect.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 = protoreflect.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  
   589  const (
   590  	secondsInNanos       = 999999999
   591  	maxSecondsInDuration = 315576000000
   592  )
   593  
   594  func (e encoder) marshalDuration(m protoreflect.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  
   626  func (d decoder) unmarshalDuration(m protoreflect.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, protoreflect.ValueOfInt64(secs))
   650  	m.Set(fdNanos, protoreflect.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.
   660  func 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  
   777  const (
   778  	maxTimestampSeconds = 253402300799
   779  	minTimestampSeconds = -62135596800
   780  )
   781  
   782  func (e encoder) marshalTimestamp(m protoreflect.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  
   808  func (d decoder) unmarshalTimestamp(m protoreflect.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  	s := tok.ParsedString()
   818  	t, err := time.Parse(time.RFC3339Nano, s)
   819  	if err != nil {
   820  		return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString())
   821  	}
   822  	// Validate seconds.
   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  	// Validate subseconds.
   828  	i := strings.LastIndexByte(s, '.')  // start of subsecond field
   829  	j := strings.LastIndexAny(s, "Z-+") // start of timezone field
   830  	if i >= 0 && j >= i && j-i > len(".999999999") {
   831  		return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString())
   832  	}
   833  
   834  	fds := m.Descriptor().Fields()
   835  	fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number)
   836  	fdNanos := fds.ByNumber(genid.Timestamp_Nanos_field_number)
   837  
   838  	m.Set(fdSeconds, protoreflect.ValueOfInt64(secs))
   839  	m.Set(fdNanos, protoreflect.ValueOfInt32(int32(t.Nanosecond())))
   840  	return nil
   841  }
   842  
   843  // The JSON representation for a FieldMask is a JSON string where paths are
   844  // separated by a comma. Fields name in each path are converted to/from
   845  // lower-camel naming conventions. Encoding should fail if the path name would
   846  // end up differently after a round-trip.
   847  
   848  func (e encoder) marshalFieldMask(m protoreflect.Message) error {
   849  	fd := m.Descriptor().Fields().ByNumber(genid.FieldMask_Paths_field_number)
   850  	list := m.Get(fd).List()
   851  	paths := make([]string, 0, list.Len())
   852  
   853  	for i := 0; i < list.Len(); i++ {
   854  		s := list.Get(i).String()
   855  		if !protoreflect.FullName(s).IsValid() {
   856  			return errors.New("%s contains invalid path: %q", genid.FieldMask_Paths_field_fullname, s)
   857  		}
   858  		// Return error if conversion to camelCase is not reversible.
   859  		cc := strs.JSONCamelCase(s)
   860  		if s != strs.JSONSnakeCase(cc) {
   861  			return errors.New("%s contains irreversible value %q", genid.FieldMask_Paths_field_fullname, s)
   862  		}
   863  		paths = append(paths, cc)
   864  	}
   865  
   866  	e.WriteString(strings.Join(paths, ","))
   867  	return nil
   868  }
   869  
   870  func (d decoder) unmarshalFieldMask(m protoreflect.Message) error {
   871  	tok, err := d.Read()
   872  	if err != nil {
   873  		return err
   874  	}
   875  	if tok.Kind() != json.String {
   876  		return d.unexpectedTokenError(tok)
   877  	}
   878  	str := strings.TrimSpace(tok.ParsedString())
   879  	if str == "" {
   880  		return nil
   881  	}
   882  	paths := strings.Split(str, ",")
   883  
   884  	fd := m.Descriptor().Fields().ByNumber(genid.FieldMask_Paths_field_number)
   885  	list := m.Mutable(fd).List()
   886  
   887  	for _, s0 := range paths {
   888  		s := strs.JSONSnakeCase(s0)
   889  		if strings.Contains(s0, "_") || !protoreflect.FullName(s).IsValid() {
   890  			return d.newError(tok.Pos(), "%v contains invalid path: %q", genid.FieldMask_Paths_field_fullname, s0)
   891  		}
   892  		list.Append(protoreflect.ValueOfString(s))
   893  	}
   894  	return nil
   895  }