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 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 "google.golang.org/protobuf/reflect/protoreflect" 21) 22 23type 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. 27func 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 61type 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. 65func 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 105func (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 166func (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 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 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 405func (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 411func (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 423func (e encoder) marshalEmpty(protoreflect.Message) error { 424 e.StartObject() 425 e.EndObject() 426 return nil 427} 428 429func (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 465func (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 470func (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 479func (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 484func (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 493func (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 507func (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 589const ( 590 secondsInNanos = 999999999 591 maxSecondsInDuration = 315576000000 592) 593 594func (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 626func (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. 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 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 808func (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 848func (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 870func (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} 896