Import upstream version 1.5.2
Debian Janitor
2 years ago
0 | on: [push, pull_request] | |
1 | name: Test | |
2 | jobs: | |
3 | test: | |
4 | strategy: | |
5 | matrix: | |
6 | go-version: [1.11.x, 1.12.x, 1.13.x, 1.14.x, 1.15.x, 1.16.x] | |
7 | os: [ubuntu-latest, macos-latest] | |
8 | runs-on: ${{ matrix.os }} | |
9 | steps: | |
10 | - name: Install Go | |
11 | uses: actions/setup-go@v2 | |
12 | with: | |
13 | go-version: ${{ matrix.go-version }} | |
14 | - name: Checkout code | |
15 | uses: actions/checkout@v2 | |
16 | - name: TestLatest | |
17 | if: matrix.go-version == '1.16.x' | |
18 | run: ./test.bash | |
19 | - name: TestAll | |
20 | if: matrix.go-version != '1.16.x' | |
21 | run: go test ./... |
0 | language: go | |
1 | before_install: | |
2 | - mkdir /tmp/go1.12 | |
3 | - curl -L -s https://dl.google.com/go/go1.12.linux-amd64.tar.gz | tar -zxf - -C /tmp/go1.12 --strip-components 1 | |
4 | - unset GOROOT | |
5 | - (GO111MODULE=on /tmp/go1.12/bin/go mod vendor) | |
6 | matrix: | |
7 | include: | |
8 | - go: 1.9.x | |
9 | script: go test -tags protolegacy -v ./... | |
10 | - go: 1.10.x | |
11 | script: go test -tags protolegacy -v ./... | |
12 | - go: 1.11.x | |
13 | script: go test -tags protolegacy -v ./... | |
14 | - go: 1.12.x | |
15 | script: ./test.bash |
78 | 78 | } |
79 | 79 | |
80 | 80 | // Obtain the raw file descriptor. |
81 | var raw []byte | |
82 | switch fd := d.(type) { | |
83 | case interface{ ProtoLegacyRawDesc() []byte }: | |
84 | raw = fd.ProtoLegacyRawDesc() | |
85 | case protoreflect.FileDescriptor: | |
86 | raw, _ = proto.Marshal(protodesc.ToFileDescriptorProto(fd)) | |
87 | } | |
88 | file := protoimpl.X.CompressGZIP(raw) | |
81 | fd := d.(protoreflect.FileDescriptor) | |
82 | b, _ := proto.Marshal(protodesc.ToFileDescriptorProto(fd)) | |
83 | file := protoimpl.X.CompressGZIP(b) | |
89 | 84 | |
90 | 85 | // Reverse the indexes, since we populated it in reverse. |
91 | 86 | for i, j := 0, len(idxs)-1; i < j; i, j = i+1, j-1 { |
0 | // Deprecated: Use the "google.golang.org/protobuf" module instead. | |
0 | 1 | module github.com/golang/protobuf |
1 | 2 | |
2 | 3 | go 1.9 |
3 | 4 | |
4 | 5 | require ( |
5 | github.com/google/go-cmp v0.4.0 | |
6 | google.golang.org/protobuf v1.23.0 | |
6 | github.com/google/go-cmp v0.5.5 | |
7 | google.golang.org/protobuf v1.26.0 | |
7 | 8 | ) |
0 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | |
1 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | |
2 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= | |
3 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | |
4 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | |
5 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |
6 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |
7 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | |
8 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |
0 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | |
1 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | |
2 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |
9 | 3 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= |
10 | 4 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
11 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | |
12 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | |
13 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | |
14 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | |
15 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | |
16 | google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= | |
17 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | |
5 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | |
6 | google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= | |
7 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= |
134 | 134 | md := m.Descriptor() |
135 | 135 | fds := md.Fields() |
136 | 136 | |
137 | if string(in) == "null" && md.FullName() != "google.protobuf.Value" { | |
138 | return nil | |
139 | } | |
140 | ||
141 | 137 | if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok { |
142 | 138 | return jsu.UnmarshalJSONPB(u, in) |
139 | } | |
140 | ||
141 | if string(in) == "null" && md.FullName() != "google.protobuf.Value" { | |
142 | return nil | |
143 | 143 | } |
144 | 144 | |
145 | 145 | switch wellKnownType(md.FullName()) { |
331 | 331 | raw = v |
332 | 332 | } |
333 | 333 | |
334 | field := m.NewField(fd) | |
334 | 335 | // Unmarshal the field value. |
335 | if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd)) { | |
336 | if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { | |
336 | 337 | continue |
337 | 338 | } |
338 | v, err := u.unmarshalValue(m.NewField(fd), raw, fd) | |
339 | v, err := u.unmarshalValue(field, raw, fd) | |
339 | 340 | if err != nil { |
340 | 341 | return err |
341 | 342 | } |
363 | 364 | return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName()) |
364 | 365 | } |
365 | 366 | |
367 | field := m.NewField(fd) | |
366 | 368 | // Unmarshal the field value. |
367 | if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd)) { | |
369 | if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { | |
368 | 370 | continue |
369 | 371 | } |
370 | v, err := u.unmarshalValue(m.NewField(fd), raw, fd) | |
372 | v, err := u.unmarshalValue(field, raw, fd) | |
371 | 373 | if err != nil { |
372 | 374 | return err |
373 | 375 | } |
385 | 387 | func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool { |
386 | 388 | if md := fd.Message(); md != nil { |
387 | 389 | return md.FullName() == "google.protobuf.Value" && fd.Cardinality() != protoreflect.Repeated |
390 | } | |
391 | return false | |
392 | } | |
393 | ||
394 | func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool { | |
395 | if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated { | |
396 | _, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler) | |
397 | return ok | |
388 | 398 | } |
389 | 399 | return false |
390 | 400 | } |
165 | 165 | fd := fds.ByNumber(1) |
166 | 166 | return w.marshalValue(fd, m.Get(fd), indent) |
167 | 167 | case "Duration": |
168 | const maxSecondsInDuration = 315576000000 | |
168 | 169 | // "Generated output always contains 0, 3, 6, or 9 fractional digits, |
169 | 170 | // depending on required precision." |
170 | 171 | s := m.Get(fds.ByNumber(1)).Int() |
171 | 172 | ns := m.Get(fds.ByNumber(2)).Int() |
173 | if s < -maxSecondsInDuration || s > maxSecondsInDuration { | |
174 | return fmt.Errorf("seconds out of range %v", s) | |
175 | } | |
172 | 176 | if ns <= -secondInNanos || ns >= secondInNanos { |
173 | 177 | return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) |
174 | 178 | } |
175 | 179 | if (s > 0 && ns < 0) || (s < 0 && ns > 0) { |
176 | 180 | return errors.New("signs of seconds and nanos do not match") |
177 | 181 | } |
178 | if s < 0 { | |
179 | ns = -ns | |
180 | } | |
181 | x := fmt.Sprintf("%d.%09d", s, ns) | |
182 | var sign string | |
183 | if s < 0 || ns < 0 { | |
184 | sign, s, ns = "-", -1*s, -1*ns | |
185 | } | |
186 | x := fmt.Sprintf("%s%d.%09d", sign, s, ns) | |
182 | 187 | x = strings.TrimSuffix(x, "000") |
183 | 188 | x = strings.TrimSuffix(x, "000") |
184 | 189 | x = strings.TrimSuffix(x, ".000") |
447 | 447 | {"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON}, |
448 | 448 | {"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON}, |
449 | 449 | {"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON}, |
450 | {"Duration", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3s"}`}, | |
451 | {"Duration", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 3, Nanos: 1e6}}, `{"dur":"3.001s"}`}, | |
452 | {"Duration beyond float64 precision", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`}, | |
453 | {"negative Duration", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -123, Nanos: -456}}, `{"dur":"-123.000000456s"}`}, | |
450 | {"Duration empty", marshaler, &durpb.Duration{}, `"0s"`}, | |
451 | {"Duration with secs", marshaler, &durpb.Duration{Seconds: 3}, `"3s"`}, | |
452 | {"Duration with -secs", marshaler, &durpb.Duration{Seconds: -3}, `"-3s"`}, | |
453 | {"Duration with nanos", marshaler, &durpb.Duration{Nanos: 1e6}, `"0.001s"`}, | |
454 | {"Duration with -nanos", marshaler, &durpb.Duration{Nanos: -1e6}, `"-0.001s"`}, | |
455 | {"Duration with large secs", marshaler, &durpb.Duration{Seconds: 1e10, Nanos: 1}, `"10000000000.000000001s"`}, | |
456 | {"Duration with 6-digit nanos", marshaler, &durpb.Duration{Nanos: 1e4}, `"0.000010s"`}, | |
457 | {"Duration with 3-digit nanos", marshaler, &durpb.Duration{Nanos: 1e6}, `"0.001s"`}, | |
458 | {"Duration with -secs -nanos", marshaler, &durpb.Duration{Seconds: -123, Nanos: -450}, `"-123.000000450s"`}, | |
459 | {"Duration max value", marshaler, &durpb.Duration{Seconds: 315576000000, Nanos: 999999999}, `"315576000000.999999999s"`}, | |
460 | {"Duration min value", marshaler, &durpb.Duration{Seconds: -315576000000, Nanos: -999999999}, `"-315576000000.999999999s"`}, | |
454 | 461 | {"Struct", marshaler, &pb2.KnownTypes{St: &stpb.Struct{ |
455 | 462 | Fields: map[string]*stpb.Value{ |
456 | 463 | "one": {Kind: &stpb.Value_StringValue{"loneliest number"}}, |
523 | 530 | pb proto.Message |
524 | 531 | fail bool |
525 | 532 | }{ |
526 | {&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 0}}, false}, | |
527 | {&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 0}}, false}, | |
528 | {&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: -1}}, true}, | |
529 | {&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 1}}, true}, | |
530 | {&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 1000000000}}, true}, | |
531 | {&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: -1000000000}}, true}, | |
532 | {&pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1}}, false}, | |
533 | {&pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: -1}}, true}, | |
534 | {&pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1000000000}}, true}, | |
533 | {&durpb.Duration{Seconds: 1, Nanos: 0}, false}, | |
534 | {&durpb.Duration{Seconds: -1, Nanos: 0}, false}, | |
535 | {&durpb.Duration{Seconds: 1, Nanos: -1}, true}, | |
536 | {&durpb.Duration{Seconds: -1, Nanos: 1}, true}, | |
537 | {&durpb.Duration{Seconds: 315576000001}, true}, | |
538 | {&durpb.Duration{Seconds: -315576000001}, true}, | |
539 | {&durpb.Duration{Seconds: 1, Nanos: 1000000000}, true}, | |
540 | {&durpb.Duration{Seconds: -1, Nanos: -1000000000}, true}, | |
541 | {&tspb.Timestamp{Seconds: 1, Nanos: 1}, false}, | |
542 | {&tspb.Timestamp{Seconds: 1, Nanos: -1}, true}, | |
543 | {&tspb.Timestamp{Seconds: 1, Nanos: 1000000000}, true}, | |
535 | 544 | } |
536 | 545 | for _, tt := range tests { |
537 | 546 | _, err := marshaler.MarshalToString(tt.pb) |
999 | 1008 | t.Errorf("unmarshal error: %v", err) |
1000 | 1009 | } |
1001 | 1010 | |
1002 | want := ptrFieldMessage{} | |
1011 | want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}} | |
1003 | 1012 | if !proto.Equal(&ptrFieldMsg, &want) { |
1004 | 1013 | t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want) |
1005 | 1014 | } |
12 | 12 | "strings" |
13 | 13 | "sync" |
14 | 14 | |
15 | "google.golang.org/protobuf/reflect/protodesc" | |
15 | 16 | "google.golang.org/protobuf/reflect/protoreflect" |
16 | 17 | "google.golang.org/protobuf/reflect/protoregistry" |
17 | 18 | "google.golang.org/protobuf/runtime/protoimpl" |
61 | 62 | // Find the descriptor in the v2 registry. |
62 | 63 | var b []byte |
63 | 64 | if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil { |
64 | if fd, ok := fd.(interface{ ProtoLegacyRawDesc() []byte }); ok { | |
65 | b = fd.ProtoLegacyRawDesc() | |
66 | } else { | |
67 | // TODO: Use protodesc.ToFileDescriptorProto to construct | |
68 | // a descriptorpb.FileDescriptorProto and marshal it. | |
69 | // However, doing so causes the proto package to have a dependency | |
70 | // on descriptorpb, leading to cyclic dependency issues. | |
71 | } | |
65 | b, _ = Marshal(protodesc.ToFileDescriptorProto(fd)) | |
72 | 66 | } |
73 | 67 | |
74 | 68 | // Locally cache the raw descriptor form for the file. |
764 | 764 | if i > utf8.MaxRune { |
765 | 765 | return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) |
766 | 766 | } |
767 | return string(i), s, nil | |
767 | return string(rune(i)), s, nil | |
768 | 768 | } |
769 | 769 | return "", "", fmt.Errorf(`unknown escape \%c`, r) |
770 | 770 | } |
18 | 18 | |
19 | 19 | // AnyMessageName returns the message name contained in an anypb.Any message. |
20 | 20 | // Most type assertions should use the Is function instead. |
21 | // | |
22 | // Deprecated: Call the any.MessageName method instead. | |
21 | 23 | func AnyMessageName(any *anypb.Any) (string, error) { |
22 | 24 | name, err := anyMessageName(any) |
23 | 25 | return string(name), err |
37 | 39 | } |
38 | 40 | |
39 | 41 | // MarshalAny marshals the given message m into an anypb.Any message. |
42 | // | |
43 | // Deprecated: Call the anypb.New function instead. | |
40 | 44 | func MarshalAny(m proto.Message) (*anypb.Any, error) { |
41 | 45 | switch dm := m.(type) { |
42 | 46 | case DynamicAny: |
57 | 61 | // Empty returns a new message of the type specified in an anypb.Any message. |
58 | 62 | // It returns protoregistry.NotFound if the corresponding message type could not |
59 | 63 | // be resolved in the global registry. |
64 | // | |
65 | // Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead | |
66 | // to resolve the message name and create a new instance of it. | |
60 | 67 | func Empty(any *anypb.Any) (proto.Message, error) { |
61 | 68 | name, err := anyMessageName(any) |
62 | 69 | if err != nil { |
75 | 82 | // |
76 | 83 | // The target message m may be a *DynamicAny message. If the underlying message |
77 | 84 | // type could not be resolved, then this returns protoregistry.NotFound. |
85 | // | |
86 | // Deprecated: Call the any.UnmarshalTo method instead. | |
78 | 87 | func UnmarshalAny(any *anypb.Any, m proto.Message) error { |
79 | 88 | if dm, ok := m.(*DynamicAny); ok { |
80 | 89 | if dm.Message == nil { |
99 | 108 | } |
100 | 109 | |
101 | 110 | // Is reports whether the Any message contains a message of the specified type. |
111 | // | |
112 | // Deprecated: Call the any.MessageIs method instead. | |
102 | 113 | func Is(any *anypb.Any, m proto.Message) bool { |
103 | 114 | if any == nil || m == nil { |
104 | 115 | return false |
118 | 129 | // var x ptypes.DynamicAny |
119 | 130 | // if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } |
120 | 131 | // fmt.Printf("unmarshaled message: %v", x.Message) |
132 | // | |
133 | // Deprecated: Use the any.UnmarshalNew method instead to unmarshal | |
134 | // the any message contents into a new instance of the underlying message. | |
121 | 135 | type DynamicAny struct{ proto.Message } |
122 | 136 | |
123 | 137 | func (m DynamicAny) String() string { |
2 | 2 | // license that can be found in the LICENSE file. |
3 | 3 | |
4 | 4 | // Package ptypes provides functionality for interacting with well-known types. |
5 | // | |
6 | // Deprecated: Well-known types have specialized functionality directly | |
7 | // injected into the generated packages for each message type. | |
8 | // See the deprecation notice for each function for the suggested alternative. | |
5 | 9 | package ptypes |
20 | 20 | |
21 | 21 | // Duration converts a durationpb.Duration to a time.Duration. |
22 | 22 | // Duration returns an error if dur is invalid or overflows a time.Duration. |
23 | // | |
24 | // Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead. | |
23 | 25 | func Duration(dur *durationpb.Duration) (time.Duration, error) { |
24 | 26 | if err := validateDuration(dur); err != nil { |
25 | 27 | return 0, err |
38 | 40 | } |
39 | 41 | |
40 | 42 | // DurationProto converts a time.Duration to a durationpb.Duration. |
43 | // | |
44 | // Deprecated: Call the durationpb.New function instead. | |
41 | 45 | func DurationProto(d time.Duration) *durationpb.Duration { |
42 | 46 | nanos := d.Nanoseconds() |
43 | 47 | secs := nanos / 1e9 |
32 | 32 | // |
33 | 33 | // A nil Timestamp returns an error. The first return value in that case is |
34 | 34 | // undefined. |
35 | // | |
36 | // Deprecated: Call the ts.AsTime and ts.CheckValid methods instead. | |
35 | 37 | func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) { |
36 | 38 | // Don't return the zero value on error, because corresponds to a valid |
37 | 39 | // timestamp. Instead return whatever time.Unix gives us. |
45 | 47 | } |
46 | 48 | |
47 | 49 | // TimestampNow returns a google.protobuf.Timestamp for the current time. |
50 | // | |
51 | // Deprecated: Call the timestamppb.Now function instead. | |
48 | 52 | func TimestampNow() *timestamppb.Timestamp { |
49 | 53 | ts, err := TimestampProto(time.Now()) |
50 | 54 | if err != nil { |
55 | 59 | |
56 | 60 | // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. |
57 | 61 | // It returns an error if the resulting Timestamp is invalid. |
62 | // | |
63 | // Deprecated: Call the timestamppb.New function instead. | |
58 | 64 | func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) { |
59 | 65 | ts := ×tamppb.Timestamp{ |
60 | 66 | Seconds: t.Unix(), |
68 | 74 | |
69 | 75 | // TimestampString returns the RFC 3339 string for valid Timestamps. |
70 | 76 | // For invalid Timestamps, it returns an error message in parentheses. |
77 | // | |
78 | // Deprecated: Call the ts.AsTime method instead, | |
79 | // followed by a call to the Format method on the time.Time value. | |
71 | 80 | func TimestampString(ts *timestamppb.Timestamp) string { |
72 | 81 | t, err := Timestamp(ts) |
73 | 82 | if err != nil { |