diff --git a/.gitignore b/.gitignore index b3baf4ab..a1f9cc2d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ /bin/ /vendor/ .#* +.aider* +debug.test* # This file includes artifacts of the system test that should not be checked in. # For files created by specific development environment (e.g. editor), diff --git a/Makefile b/Makefile index 852444a4..b1a4e61b 100644 --- a/Makefile +++ b/Makefile @@ -83,6 +83,7 @@ gengo: $(GOIMPORTS) $(PROTOWRAP) $(PROTOC_GEN_GO) --proto_path $$(pwd)/vendor \ --print_structure \ --only_specified_files \ + $$2 \ $$(\ git \ ls-files "$$1" |\ @@ -90,9 +91,9 @@ gengo: $(GOIMPORTS) $(PROTOWRAP) $(PROTOC_GEN_GO) "$$(pwd)/vendor/$${PROJECT}/%s "); \ }; \ for d in ./types/known/*; do \ - protogen "$${d}/*.proto"; \ + protogen "$${d}/*.proto" "--go-lite_opt=features=marshal+marshal_strict+unmarshal+unmarshal_unsafe+size+equal+clone"; \ done; \ - protogen "./types/descriptorpb/*.proto"; \ - protogen "./testproto/*.proto"; \ + protogen "./types/descriptorpb/*.proto" ""; \ + protogen "./testproto/*.proto" ""; \ rm $$(pwd)/vendor/$${PROJECT} || true $(GOIMPORTS) -w ./ diff --git a/features/json/enums-unmarshal.go b/features/json/enums-unmarshal.go new file mode 100644 index 00000000..3863c1d1 --- /dev/null +++ b/features/json/enums-unmarshal.go @@ -0,0 +1,42 @@ +// Copyright © 2024 Aperture Robotics, LLC. +// Copyright © 2021 The Things Industries B.V. +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + "github.com/aperturerobotics/protobuf-go-lite/compiler/protogen" +) + +func (g *jsonGenerator) genEnumUnmarshaler(enum *protogen.Enum) { + g.P("// UnmarshalProtoJSON unmarshals the ", enum.GoIdent, " from JSON.") + g.P("func (x *", enum.GoIdent, ") UnmarshalProtoJSON(s *", jsonPluginPackage.Ident("UnmarshalState"), ") {") + // We read the enum, passing only the original mapping to the unmarshaler. + g.P("v := s.ReadEnum(", enum.GoIdent, "_value)") + g.P("if err := s.Err(); err != nil {") + g.P(`s.SetErrorf("could not read `, enum.Desc.Name(), ` enum: %v", err)`) + g.P("return") + g.P("}") + g.P("*x = ", enum.GoIdent, "(v)") + g.P("}") + g.P() +} + +func (g *jsonGenerator) genStdEnumUnmarshaler(enum *protogen.Enum) { + g.P("// UnmarshalText unmarshals the ", enum.GoIdent, " from text.") + g.P("func (x *", enum.GoIdent, ") UnmarshalText(b []byte) error {") + g.P("i, err := ", jsonPluginPackage.Ident("ParseEnumString"), "(string(b), ", enum.GoIdent, "_value)") + g.P("if err != nil {") + g.P("return err") + g.P("}") + g.P("*x = ", enum.GoIdent, "(i)") + g.P("return nil") + g.P("}") + g.P() + + g.P("// UnmarshalJSON unmarshals the ", enum.GoIdent, " from JSON.") + g.P("func (x *", enum.GoIdent, ") UnmarshalJSON(b []byte) error {") + g.P("return ", jsonPluginPackage.Ident("DefaultUnmarshalerConfig"), ".Unmarshal(b, x)") + g.P("}") + g.P() +} diff --git a/features/json/enums.go b/features/json/enums.go index b8cc6609..3d3f22ed 100644 --- a/features/json/enums.go +++ b/features/json/enums.go @@ -11,4 +11,7 @@ import ( func (g *jsonGenerator) genEnum(enum *protogen.Enum) { g.genEnumMarshaler(enum) g.genStdEnumMarshaler(enum) + + g.genEnumUnmarshaler(enum) + g.genStdEnumUnmarshaler(enum) } diff --git a/features/json/message-marshal.go b/features/json/message-marshal.go index beaade09..0c41079c 100644 --- a/features/json/message-marshal.go +++ b/features/json/message-marshal.go @@ -126,7 +126,7 @@ nextField: g.P(`element.MarshalProtoJSON(s.WithField("`, field.Desc.Name(), `"))`) // Otherwise delegate to the library. // g.P("// NOTE: ", field.Message.GoIdent.GoName, " does not seem to implement MarshalProtoJSON.") - // g.P(pluginPackage.Ident("MarshalMessage"), "(s, ", ifThenElse(nullable, "", "&"), "element)") + // g.P(jsonPluginPackage.Ident("MarshalMessage"), "(s, ", ifThenElse(nullable, "", "&"), "element)") g.P("}") // end for _, element := range x.{fieldGoName} { g.P("s.WriteArrayEnd()") @@ -202,7 +202,7 @@ nextField: g.P(messageOrOneofIdent, ".", fieldGoName, `.MarshalProtoJSON(s.WithField("`, field.Desc.Name(), `"))`) // Otherwise delegate to the library. // g.P("// NOTE: ", field.Message.GoIdent.GoName, " does not seem to implement MarshalProtoJSON.") - // g.P(pluginPackage.Ident("MarshalMessage"), "(s, ", ifThenElse(nullable, "", "&"), messageOrOneofIdent, ".", fieldGoName, ")") + // g.P(jsonPluginPackage.Ident("MarshalMessage"), "(s, ", ifThenElse(nullable, "", "&"), messageOrOneofIdent, ".", fieldGoName, ")") } // If we're not in a oneof, end the "if not zero". diff --git a/features/json/message-unmarshal.go b/features/json/message-unmarshal.go new file mode 100644 index 00000000..0e1c15c4 --- /dev/null +++ b/features/json/message-unmarshal.go @@ -0,0 +1,272 @@ +// Copyright © 2024 Aperture Robotics, LLC. +// Copyright © 2021 The Things Industries B.V. +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + "fmt" + + "github.com/aperturerobotics/protobuf-go-lite/compiler/protogen" + "google.golang.org/protobuf/reflect/protoreflect" +) + +func (g *jsonGenerator) genMessageUnmarshaler(message *protogen.Message) { + g.P("// UnmarshalProtoJSON unmarshals the ", message.GoIdent, " message from JSON.") + g.P("func (x *", message.GoIdent, ") UnmarshalProtoJSON(s *", jsonPluginPackage.Ident("UnmarshalState"), ") {") + + // If we se a null, there's nothing to do. + g.P("if s.ReadNil() {") + g.P("return") + g.P("}") + + // If the message doesn't have any fields, there's nothing to do. + if len(message.Fields) == 0 { + g.P("}") // end func (x *{message.GoIdent}) MarshalProtoJSON() + g.P() + return + } + + g.P("s.ReadObject(func(key string) {") + g.P("switch key {") + g.P("default:") + g.P("s.ReadAny() // ignore unknown field") + +nextField: + for _, field := range message.Fields { + var ( + fieldGoName interface{} = fieldGoName(field) + nullable = fieldIsNullable(field) + ) + + // We need to match both the snake case field name and the camel case JSON name. + // If those are the same, we only need to match one. + if string(field.Desc.Name()) != field.Desc.JSONName() { + g.P(`case "`, field.Desc.Name(), `", "`, field.Desc.JSONName(), `":`) + } else { + g.P(`case "`, field.Desc.Name(), `":`) + } + + // For sub-messages, field mask handling will be handled by the unmarshaler of the sub-message. + // For scalar types and fields that don't support field masks (lists, maps, fields without unmarshalers) we do field mask handling here. + delegateMask := "true" + if field.Message == nil || field.Desc.IsList() || field.Desc.IsMap() { + delegateMask = "false" + g.P(`s.AddField("`, field.Desc.Name(), `")`) + } + + if field.Desc.IsMap() { + // If we read null, set the field to nil. + g.P("if s.ReadNil() {") + g.P("x.", fieldGoName, " = nil") + g.P("return") + g.P("}") + + // If the field is a map, the field type is a MapEntry message. + // In the MapEntry message, the first field is the key, and the second field is the value. + key := field.Message.Fields[0] + value := field.Message.Fields[1] + + // Allocate an empty map[T(key)]T(value). + g.P("x.", fieldGoName, " = make(map[", g.goTypeForField(key), "]", ifThenElse(fieldIsNullable(value), "*", ""), g.goTypeForField(value), ")") + + // Tell the library to read a map with keys of the given type, passing our handler func that will be called for each key. + g.P("s.Read", g.libNameForField(key), "Map(func(key ", g.goTypeForField(key), ") {") + + switch value.Desc.Kind() { + default: + // Scalar types can be read by the library. + g.P("x.", fieldGoName, "[key] = s.Read", g.libNameForField(value), "()") + case protoreflect.EnumKind: + // If the map value is of type enum, and the enum has an unmarshaler, + // allocate a zero enum, call the unmarshaler, and set the map value for key to the enum. + g.P("var v ", value.Enum.GoIdent) + g.P(`v.UnmarshalProtoJSON(s)`) + g.P("x.", fieldGoName, "[key] = v") + case protoreflect.MessageKind: + // If the map value is of type message, and the message has a marshaler, + // allocate a zero message, call the unmarshaler and set the map value for the key to the message. + g.P("var v ", value.Message.GoIdent) + g.P(`v.UnmarshalProtoJSON(s)`) + g.P("x.", fieldGoName, "[key] = &v") + + // Otherwise, delegate to the library. + /* + g.P("// NOTE: ", value.Message.GoIdent.GoName, " does not seem to implement UnmarshalProtoJSON.") + g.P("var v ", value.Message.GoIdent) + g.P(pluginPackage.Ident("UnmarshalMessage"), "(s, &v)") + g.P("x.", fieldGoName, "[key] = &v") + */ + } + + g.P("})") // end s.Read{key}Map() + continue nextField + } + + if field.Desc.IsList() { + // If we read null, set the field to nil. + g.P("if s.ReadNil() {") + g.P("x.", fieldGoName, " = nil") + g.P("return") + g.P("}") + + switch field.Desc.Kind() { + default: + // Lists of scalar types can be read by the library. + g.P("x.", fieldGoName, " = s.Read", g.libNameForField(field), "Array()") + case protoreflect.EnumKind: + g.P("s.ReadArray(func() {") + // If the list value is of type enum, and the enum has an unmarshaler, + // allocate a zero enum, call the unmarshaler, and append the enum to the list. + g.P("var v ", field.Enum.GoIdent) + g.P(`v.UnmarshalProtoJSON(s)`) + g.P("x.", fieldGoName, " = append(x.", fieldGoName, ", v)") + + // Otherwise we let the library read the enum. + // g.P("x.", fieldGoName, " = append(x.", fieldGoName, ", ", field.Enum.GoIdent, "(s.ReadEnum(", field.Enum.GoIdent, "_value)))") + + g.P("})") // end s.ReadArray() + case protoreflect.MessageKind: + g.P("s.ReadArray(func() {") + + if nullable { + // If we read nil, append nil and return so that we can continue with the next key. + g.P("if s.ReadNil() {") + g.P("x.", fieldGoName, " = append(x.", fieldGoName, ", nil)") + g.P("return") + g.P("}") // end if s.ReadNil() { + } + // Allocate a zero message, call the unmarshaler and append the message to the list. + g.P("v := ", ifThenElse(nullable, "&", ""), field.Message.GoIdent, "{}") + g.P(`v.UnmarshalProtoJSON(s.WithField("`, field.Desc.Name(), `", `, delegateMask, `))`) + g.P("if s.Err() != nil {") + g.P("return") + g.P("}") + g.P("x.", fieldGoName, " = append(x.", fieldGoName, ", v)") + + // Otherwise, delegate to the library. + /* + g.P("// NOTE: ", field.Message.GoIdent.GoName, " does not seem to implement UnmarshalProtoJSON.") + g.P("var v ", field.Message.GoIdent) + g.P(pluginPackage.Ident("UnmarshalMessage"), "(s, &v)") + g.P("x.", fieldGoName, " = append(x.", fieldGoName, ", ", ifThenElse(nullable, "&", ""), "v)") + */ + + g.P("})") // end s.ReadArray() + } + + continue nextField + } + + // The identifier of the message is x, but in case of a oneof, we'll be operating on ov. + messageOrOneofIdent := "x" + + // If this field is in a oneof, allocate a new oneof value wrapper. + if field.Oneof != nil { + g.P("ov := &", field.GoIdent.GoName, "{}") + g.P("x.", field.Oneof.GoName, " = ov") + messageOrOneofIdent = "ov" + } + + // If the field is nullable (it's a message, or bytes with custom type) + // and we read null, set the field to nil. + if nullable { + g.P("if s.ReadNil() {") + // If the field is a google.protobuf.Value, instead of nil, we write a google.protobuf.NullValue. + if field.Message != nil && field.Message.Desc.FullName() == "google.protobuf.Value" { + g.P( + messageOrOneofIdent, ".", fieldGoName, " = &", field.Message.GoIdent, "{", + "Kind: &", field.Message.GoIdent.GoImportPath.Ident("Value_NullValue"), "{},", + "}", + ) + } else { + g.P(messageOrOneofIdent, ".", fieldGoName, " = nil") + } + g.P("return") + g.P("}") + } + + // If the field has a custom unmarshaler, call that + switch field.Desc.Kind() { + default: + // Scalar types can be read by the library. + g.P(messageOrOneofIdent, ".", fieldGoName, " = s.Read", g.libNameForField(field), "()") + case protoreflect.EnumKind: + // If the field is of type enum, and the enum has an unmarshaler, call the unmarshaler. + g.P(messageOrOneofIdent, ".", fieldGoName, ".UnmarshalProtoJSON(s)") + + // Otherwise we let the library read the enum. + // g.P(messageOrOneofIdent, ".", fieldGoName, " = ", field.Enum.GoIdent, "(s.ReadEnum(", field.Enum.GoIdent, "_value))") + case protoreflect.MessageKind: + if nullable { + // Set the field (or enum wrapper) to a newly allocated custom type. + g.P(messageOrOneofIdent, ".", fieldGoName, " = &", field.Message.GoIdent, "{}") + } + // Call UnmarshalProtoJSON on the field. + g.P(messageOrOneofIdent, ".", fieldGoName, `.UnmarshalProtoJSON(s.WithField("`, field.Desc.Name(), `", `, delegateMask, `))`) + + // Otherwise, delegate to the library. + /* + g.P("// NOTE: ", field.Message.GoIdent.GoName, " does not seem to implement UnmarshalProtoJSON.") + g.P("var v ", field.Message.GoIdent) + g.P(pluginPackage.Ident("UnmarshalMessage"), "(s, &v)") + g.P(messageOrOneofIdent, ".", fieldGoName, " = ", ifThenElse(nullable, "&", ""), "v") + */ + } + + if field.Oneof != nil { + continue nextField + } + } + + g.P("}") // end switch key { + g.P("})") // end s.ReadObject() + g.P("}") // end func (x *{message.GoIdent}) MarshalProtoJSON() + g.P() +} + +func (g *jsonGenerator) genStdMessageUnmarshaler(message *protogen.Message) { + g.P("// UnmarshalJSON unmarshals the ", message.GoIdent, " from JSON.") + g.P("func (x *", message.GoIdent, ") UnmarshalJSON(b []byte) error {") + g.P("return ", jsonPluginPackage.Ident("DefaultUnmarshalerConfig"), ".Unmarshal(b, x)") + g.P("}") + g.P() +} + +func ifThenElse(condition bool, ifTrue, ifFalse string) string { + if condition { + return ifTrue + } + return ifFalse +} + +// goTypeForField returns the name of the Go type that corresponds to the type of a given field. +func (g *jsonGenerator) goTypeForField(field *protogen.Field) interface{} { + switch field.Desc.Kind() { + case protoreflect.BoolKind: + return "bool" + case protoreflect.EnumKind: + return field.Enum.GoIdent + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: + return "int32" + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: + return "uint32" + case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + return "int64" + case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + return "uint64" + case protoreflect.FloatKind: + return "float32" + case protoreflect.DoubleKind: + return "float64" + case protoreflect.StringKind: + return "string" + case protoreflect.BytesKind: + return "[]byte" + case protoreflect.MessageKind: + return field.Message.GoIdent + default: + g.gen.Error(fmt.Errorf("unsupported field kind %q", field.Desc.Kind())) + return "" + } +} diff --git a/features/json/message.go b/features/json/message.go index 2b24ecd2..5426a5a2 100644 --- a/features/json/message.go +++ b/features/json/message.go @@ -31,6 +31,9 @@ func (g *jsonGenerator) genMessage(message *protogen.Message) { if !anyOptional { g.genMessageMarshaler(message) g.genStdMessageMarshaler(message) + + g.genMessageUnmarshaler(message) + g.genStdMessageUnmarshaler(message) } else { // We do not support marshaling this field, skip the entire message. g.P("// NOTE: protobuf-go-lite json only supports proto3 and not proto3opt (optional fields).") diff --git a/features/marshal/marshalto.go b/features/marshal/marshalto.go index 9d084423..f0a6e769 100644 --- a/features/marshal/marshalto.go +++ b/features/marshal/marshalto.go @@ -23,6 +23,7 @@ func init() { generator.RegisterFeature("marshal", func(gen *generator.GeneratedFile) generator.FeatureGenerator { return &marshal{GeneratedFile: gen, Stable: false, strict: false} }) + generator.RegisterFeature("marshal_strict", func(gen *generator.GeneratedFile) generator.FeatureGenerator { return &marshal{GeneratedFile: gen, Stable: false, strict: true} }) diff --git a/json/marshal.go b/json/marshal.go index a44c18f6..0a109240 100644 --- a/json/marshal.go +++ b/json/marshal.go @@ -11,6 +11,7 @@ import ( "strings" "time" + anypb_resolver "github.com/aperturerobotics/protobuf-go-lite/types/known/anypb/resolver" jsoniter "github.com/json-iterator/go" ) @@ -38,6 +39,9 @@ func (e *marshalError) Unwrap() error { // MarshalerConfig is the configuration for the Marshaler. type MarshalerConfig struct { EnumsAsInts bool + + // AnyTypeResolver is the resolver function for the any well-known type. + AnyTypeResolver anypb_resolver.AnyTypeResolver } // DefaultMarshalerConfig is the default configuration for the Marshaler. @@ -79,6 +83,14 @@ func (s *MarshalState) Config() MarshalerConfig { return *s.config } +// AnyTypeResolver returns the any type resolver. +func (s *MarshalState) AnyTypeResolver() anypb_resolver.AnyTypeResolver { + if s.config.AnyTypeResolver != nil { + return s.config.AnyTypeResolver + } + return anypb_resolver.NewErrAnyTypeResolver(anypb_resolver.ErrNoAnyTypeResolver) +} + // Sub returns a sub-marshaler with a new buffer, but with the same configuration, error and path info. func (s *MarshalState) Sub() *MarshalState { return &MarshalState{ diff --git a/json/unmarshal.go b/json/unmarshal.go index 7b830342..fc287e6d 100644 --- a/json/unmarshal.go +++ b/json/unmarshal.go @@ -11,6 +11,7 @@ import ( "strings" "time" + anypb_resolver "github.com/aperturerobotics/protobuf-go-lite/types/known/anypb/resolver" jsoniter "github.com/json-iterator/go" ) @@ -36,7 +37,10 @@ func (e *unmarshalError) Unwrap() error { } // UnmarshalerConfig is the configuration for the Unmarshaler. -type UnmarshalerConfig struct{} +type UnmarshalerConfig struct { + // AnyTypeResolver is the resolver function for the any well-known type. + AnyTypeResolver anypb_resolver.AnyTypeResolver +} // DefaultUnmarshalerConfig is the default configuration for the Unmarshaler. var DefaultUnmarshalerConfig = UnmarshalerConfig{} @@ -75,6 +79,14 @@ func (s *UnmarshalState) Config() UnmarshalerConfig { return *s.config } +// AnyTypeResolver returns the any type resolver. +func (s *UnmarshalState) AnyTypeResolver() anypb_resolver.AnyTypeResolver { + if s.config.AnyTypeResolver != nil { + return s.config.AnyTypeResolver + } + return anypb_resolver.NewErrAnyTypeResolver(anypb_resolver.ErrNoAnyTypeResolver) +} + // Sub returns a subunmarshaler with a new buffer, but with the same configuration, error and path info. func (s *UnmarshalState) Sub(data []byte) *UnmarshalState { return &UnmarshalState{ @@ -809,6 +821,7 @@ func (s *UnmarshalState) ReadDuration() *time.Duration { if s.ReadNil() { return nil } + // handle if we are reading an object with a "value" field d, err := time.ParseDuration(s.inner.ReadString()) if err != nil { s.SetErrorf("invalid duration: %w", err) diff --git a/testproto/maps/maps.pb.go b/testproto/maps/maps.pb.go index 2ed0fa9e..4f46dc94 100644 --- a/testproto/maps/maps.pb.go +++ b/testproto/maps/maps.pb.go @@ -205,6 +205,34 @@ func (x *MsgWithMaps_StringKeysEntry) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the MsgWithMaps_StringKeysEntry message from JSON. +func (x *MsgWithMaps_StringKeysEntry) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "key": + s.AddField("key") + x.Key = s.ReadString() + case "value": + if s.ReadNil() { + x.Value = nil + return + } + x.Value = ×tamppb.Timestamp{} + x.Value.UnmarshalProtoJSON(s.WithField("value", true)) + } + }) +} + +// UnmarshalJSON unmarshals the MsgWithMaps_StringKeysEntry from JSON. +func (x *MsgWithMaps_StringKeysEntry) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the MsgWithMaps_IntKeysEntry message to JSON. func (x *MsgWithMaps_IntKeysEntry) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -231,6 +259,34 @@ func (x *MsgWithMaps_IntKeysEntry) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the MsgWithMaps_IntKeysEntry message from JSON. +func (x *MsgWithMaps_IntKeysEntry) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "key": + s.AddField("key") + x.Key = s.ReadUint32() + case "value": + if s.ReadNil() { + x.Value = nil + return + } + x.Value = ×tamppb.Timestamp{} + x.Value.UnmarshalProtoJSON(s.WithField("value", true)) + } + }) +} + +// UnmarshalJSON unmarshals the MsgWithMaps_IntKeysEntry from JSON. +func (x *MsgWithMaps_IntKeysEntry) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the MsgWithMaps message to JSON. func (x *MsgWithMaps) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -271,6 +327,48 @@ func (x *MsgWithMaps) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the MsgWithMaps message from JSON. +func (x *MsgWithMaps) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "stringKeys": + s.AddField("stringKeys") + if s.ReadNil() { + x.StringKeys = nil + return + } + x.StringKeys = make(map[string]*timestamppb.Timestamp) + s.ReadStringMap(func(key string) { + var v timestamppb.Timestamp + v.UnmarshalProtoJSON(s) + x.StringKeys[key] = &v + }) + case "intKeys": + s.AddField("intKeys") + if s.ReadNil() { + x.IntKeys = nil + return + } + x.IntKeys = make(map[uint32]*timestamppb.Timestamp) + s.ReadUint32Map(func(key uint32) { + var v timestamppb.Timestamp + v.UnmarshalProtoJSON(s) + x.IntKeys[key] = &v + }) + } + }) +} + +// UnmarshalJSON unmarshals the MsgWithMaps from JSON. +func (x *MsgWithMaps) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + func (m *MsgWithMaps) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/testproto/proto3opt/opt.pb.go b/testproto/proto3opt/opt.pb.go index 62f3db3f..b0f4e78c 100644 --- a/testproto/proto3opt/opt.pb.go +++ b/testproto/proto3opt/opt.pb.go @@ -351,6 +351,31 @@ func (x SimpleEnum) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the SimpleEnum from JSON. +func (x *SimpleEnum) UnmarshalProtoJSON(s *json.UnmarshalState) { + v := s.ReadEnum(SimpleEnum_value) + if err := s.Err(); err != nil { + s.SetErrorf("could not read SimpleEnum enum: %v", err) + return + } + *x = SimpleEnum(v) +} + +// UnmarshalText unmarshals the SimpleEnum from text. +func (x *SimpleEnum) UnmarshalText(b []byte) error { + i, err := json.ParseEnumString(string(b), SimpleEnum_value) + if err != nil { + return err + } + *x = SimpleEnum(i) + return nil +} + +// UnmarshalJSON unmarshals the SimpleEnum from JSON. +func (x *SimpleEnum) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // NOTE: protobuf-go-lite json only supports proto3 and not proto3opt (optional fields). func (m *OptionalFieldInProto3) MarshalVT() (dAtA []byte, err error) { diff --git a/testproto/unsafe/unsafe.pb.go b/testproto/unsafe/unsafe.pb.go index 2fa1909a..96912630 100644 --- a/testproto/unsafe/unsafe.pb.go +++ b/testproto/unsafe/unsafe.pb.go @@ -855,6 +855,30 @@ func (x *UnsafeTest_Sub1) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest_Sub1 message from JSON. +func (x *UnsafeTest_Sub1) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "s": + s.AddField("s") + x.S = s.ReadString() + case "b": + s.AddField("b") + x.B = s.ReadBytes() + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest_Sub1 from JSON. +func (x *UnsafeTest_Sub1) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the UnsafeTest_Sub2 message to JSON. func (x *UnsafeTest_Sub2) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -881,6 +905,38 @@ func (x *UnsafeTest_Sub2) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest_Sub2 message from JSON. +func (x *UnsafeTest_Sub2) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "s": + s.AddField("s") + if s.ReadNil() { + x.S = nil + return + } + x.S = s.ReadStringArray() + case "b": + s.AddField("b") + if s.ReadNil() { + x.B = nil + return + } + x.B = s.ReadBytesArray() + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest_Sub2 from JSON. +func (x *UnsafeTest_Sub2) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the UnsafeTest_Sub3_FooEntry message to JSON. func (x *UnsafeTest_Sub3_FooEntry) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -907,6 +963,30 @@ func (x *UnsafeTest_Sub3_FooEntry) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest_Sub3_FooEntry message from JSON. +func (x *UnsafeTest_Sub3_FooEntry) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "key": + s.AddField("key") + x.Key = s.ReadString() + case "value": + s.AddField("value") + x.Value = s.ReadBytes() + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest_Sub3_FooEntry from JSON. +func (x *UnsafeTest_Sub3_FooEntry) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the UnsafeTest_Sub3 message to JSON. func (x *UnsafeTest_Sub3) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -935,6 +1015,34 @@ func (x *UnsafeTest_Sub3) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest_Sub3 message from JSON. +func (x *UnsafeTest_Sub3) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "foo": + s.AddField("foo") + if s.ReadNil() { + x.Foo = nil + return + } + x.Foo = make(map[string][]byte) + s.ReadStringMap(func(key string) { + x.Foo[key] = s.ReadBytes() + }) + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest_Sub3 from JSON. +func (x *UnsafeTest_Sub3) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the UnsafeTest_Sub4 message to JSON. func (x *UnsafeTest_Sub4) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -963,6 +1071,34 @@ func (x *UnsafeTest_Sub4) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest_Sub4 message from JSON. +func (x *UnsafeTest_Sub4) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "s": + s.AddField("s") + ov := &UnsafeTest_Sub4_S{} + x.Foo = ov + ov.S = s.ReadString() + case "b": + s.AddField("b") + ov := &UnsafeTest_Sub4_B{} + x.Foo = ov + ov.B = s.ReadBytes() + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest_Sub4 from JSON. +func (x *UnsafeTest_Sub4) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the UnsafeTest_Sub5_FooEntry message to JSON. func (x *UnsafeTest_Sub5_FooEntry) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -989,6 +1125,30 @@ func (x *UnsafeTest_Sub5_FooEntry) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest_Sub5_FooEntry message from JSON. +func (x *UnsafeTest_Sub5_FooEntry) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "key": + s.AddField("key") + x.Key = s.ReadString() + case "value": + s.AddField("value") + x.Value = s.ReadString() + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest_Sub5_FooEntry from JSON. +func (x *UnsafeTest_Sub5_FooEntry) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the UnsafeTest_Sub5 message to JSON. func (x *UnsafeTest_Sub5) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -1017,6 +1177,34 @@ func (x *UnsafeTest_Sub5) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest_Sub5 message from JSON. +func (x *UnsafeTest_Sub5) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "foo": + s.AddField("foo") + if s.ReadNil() { + x.Foo = nil + return + } + x.Foo = make(map[string]string) + s.ReadStringMap(func(key string) { + x.Foo[key] = s.ReadString() + }) + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest_Sub5 from JSON. +func (x *UnsafeTest_Sub5) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // MarshalProtoJSON marshals the UnsafeTest message to JSON. func (x *UnsafeTest) MarshalProtoJSON(s *json.MarshalState) { if x == nil { @@ -1057,6 +1245,69 @@ func (x *UnsafeTest) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the UnsafeTest message from JSON. +func (x *UnsafeTest) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "sub1": + ov := &UnsafeTest_Sub1_{} + x.Sub = ov + if s.ReadNil() { + ov.Sub1 = nil + return + } + ov.Sub1 = &UnsafeTest_Sub1{} + ov.Sub1.UnmarshalProtoJSON(s.WithField("sub1", true)) + case "sub2": + ov := &UnsafeTest_Sub2_{} + x.Sub = ov + if s.ReadNil() { + ov.Sub2 = nil + return + } + ov.Sub2 = &UnsafeTest_Sub2{} + ov.Sub2.UnmarshalProtoJSON(s.WithField("sub2", true)) + case "sub3": + ov := &UnsafeTest_Sub3_{} + x.Sub = ov + if s.ReadNil() { + ov.Sub3 = nil + return + } + ov.Sub3 = &UnsafeTest_Sub3{} + ov.Sub3.UnmarshalProtoJSON(s.WithField("sub3", true)) + case "sub4": + ov := &UnsafeTest_Sub4_{} + x.Sub = ov + if s.ReadNil() { + ov.Sub4 = nil + return + } + ov.Sub4 = &UnsafeTest_Sub4{} + ov.Sub4.UnmarshalProtoJSON(s.WithField("sub4", true)) + case "sub5": + ov := &UnsafeTest_Sub5_{} + x.Sub = ov + if s.ReadNil() { + ov.Sub5 = nil + return + } + ov.Sub5 = &UnsafeTest_Sub5{} + ov.Sub5.UnmarshalProtoJSON(s.WithField("sub5", true)) + } + }) +} + +// UnmarshalJSON unmarshals the UnsafeTest from JSON. +func (x *UnsafeTest) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + func (m *UnsafeTest_Sub1) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/testproto/wkt/wkt.pb.go b/testproto/wkt/wkt.pb.go index 24e43f01..fefba9d9 100644 --- a/testproto/wkt/wkt.pb.go +++ b/testproto/wkt/wkt.pb.go @@ -398,6 +398,139 @@ func (x *MessageWithWKT) MarshalJSON() ([]byte, error) { return json.DefaultMarshalerConfig.Marshal(x) } +// UnmarshalProtoJSON unmarshals the MessageWithWKT message from JSON. +func (x *MessageWithWKT) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + switch key { + default: + s.ReadAny() // ignore unknown field + case "any": + if s.ReadNil() { + x.Any = nil + return + } + x.Any = &anypb.Any{} + x.Any.UnmarshalProtoJSON(s.WithField("any", true)) + case "duration": + if s.ReadNil() { + x.Duration = nil + return + } + x.Duration = &durationpb.Duration{} + x.Duration.UnmarshalProtoJSON(s.WithField("duration", true)) + case "empty": + if s.ReadNil() { + x.Empty = nil + return + } + x.Empty = &emptypb.Empty{} + x.Empty.UnmarshalProtoJSON(s.WithField("empty", true)) + case "timestamp": + if s.ReadNil() { + x.Timestamp = nil + return + } + x.Timestamp = ×tamppb.Timestamp{} + x.Timestamp.UnmarshalProtoJSON(s.WithField("timestamp", true)) + case "double_value", "doubleValue": + if s.ReadNil() { + x.DoubleValue = nil + return + } + x.DoubleValue = &wrapperspb.DoubleValue{} + x.DoubleValue.UnmarshalProtoJSON(s.WithField("double_value", true)) + case "float_value", "floatValue": + if s.ReadNil() { + x.FloatValue = nil + return + } + x.FloatValue = &wrapperspb.FloatValue{} + x.FloatValue.UnmarshalProtoJSON(s.WithField("float_value", true)) + case "int64_value", "int64Value": + if s.ReadNil() { + x.Int64Value = nil + return + } + x.Int64Value = &wrapperspb.Int64Value{} + x.Int64Value.UnmarshalProtoJSON(s.WithField("int64_value", true)) + case "uint64_value", "uint64Value": + if s.ReadNil() { + x.Uint64Value = nil + return + } + x.Uint64Value = &wrapperspb.UInt64Value{} + x.Uint64Value.UnmarshalProtoJSON(s.WithField("uint64_value", true)) + case "int32_value", "int32Value": + if s.ReadNil() { + x.Int32Value = nil + return + } + x.Int32Value = &wrapperspb.Int32Value{} + x.Int32Value.UnmarshalProtoJSON(s.WithField("int32_value", true)) + case "uint32_value", "uint32Value": + if s.ReadNil() { + x.Uint32Value = nil + return + } + x.Uint32Value = &wrapperspb.UInt32Value{} + x.Uint32Value.UnmarshalProtoJSON(s.WithField("uint32_value", true)) + case "bool_value", "boolValue": + if s.ReadNil() { + x.BoolValue = nil + return + } + x.BoolValue = &wrapperspb.BoolValue{} + x.BoolValue.UnmarshalProtoJSON(s.WithField("bool_value", true)) + case "string_value", "stringValue": + if s.ReadNil() { + x.StringValue = nil + return + } + x.StringValue = &wrapperspb.StringValue{} + x.StringValue.UnmarshalProtoJSON(s.WithField("string_value", true)) + case "bytes_value", "bytesValue": + if s.ReadNil() { + x.BytesValue = nil + return + } + x.BytesValue = &wrapperspb.BytesValue{} + x.BytesValue.UnmarshalProtoJSON(s.WithField("bytes_value", true)) + case "struct_value", "structValue": + if s.ReadNil() { + x.StructValue = nil + return + } + x.StructValue = &structpb.Struct{} + x.StructValue.UnmarshalProtoJSON(s.WithField("struct_value", true)) + case "value_value", "valueValue": + if s.ReadNil() { + x.ValueValue = &structpb.Value{Kind: &structpb.Value_NullValue{}} + return + } + x.ValueValue = &structpb.Value{} + x.ValueValue.UnmarshalProtoJSON(s.WithField("value_value", true)) + case "listvalue_value", "listvalueValue": + if s.ReadNil() { + x.ListvalueValue = nil + return + } + x.ListvalueValue = &structpb.ListValue{} + x.ListvalueValue.UnmarshalProtoJSON(s.WithField("listvalue_value", true)) + case "null_value", "nullValue": + s.AddField("null_value") + x.NullValue.UnmarshalProtoJSON(s) + } + }) +} + +// UnmarshalJSON unmarshals the MessageWithWKT from JSON. +func (x *MessageWithWKT) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + func (m *MessageWithWKT) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/testproto/wkt/wkt_test.go b/testproto/wkt/wkt_test.go index 71568e09..24c30e56 100644 --- a/testproto/wkt/wkt_test.go +++ b/testproto/wkt/wkt_test.go @@ -6,7 +6,10 @@ import ( "github.com/stretchr/testify/require" + protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" + "github.com/aperturerobotics/protobuf-go-lite/json" "github.com/aperturerobotics/protobuf-go-lite/types/known/anypb" + anypb_resolver "github.com/aperturerobotics/protobuf-go-lite/types/known/anypb/resolver" "github.com/aperturerobotics/protobuf-go-lite/types/known/durationpb" "github.com/aperturerobotics/protobuf-go-lite/types/known/emptypb" "github.com/aperturerobotics/protobuf-go-lite/types/known/timestamppb" @@ -16,6 +19,12 @@ import ( func TestWellKnownTypes(t *testing.T) { dur := durationpb.New(4*time.Hour + 2*time.Second) + anyTypeResolver := anypb_resolver.NewFuncAnyTypeResolver(func(url string) (func() protobuf_go_lite.Message, error) { + if url == "cool.apps/test-value" { + return func() protobuf_go_lite.Message { return &durationpb.Duration{} }, nil + } + return nil, nil + }) anyVal, err := anypb.New(dur, "cool.apps/test-value") require.NoError(t, err) @@ -52,13 +61,24 @@ func TestWellKnownTypes(t *testing.T) { // assert.Equal(t, golangMsg.String(), vtProtoMsg.String()) // TODO protoc json - jdata, err := m.MarshalJSON() + mc := json.MarshalerConfig{ + AnyTypeResolver: anyTypeResolver, + } + jdata, err := mc.Marshal(m) if err != nil { require.NoError(t, err) } t.Log(string(jdata)) // Ensure output is consistent - var expected = `{"any":{"type_url":"cool.apps/test-value","value":"CMJw"},"duration":{"seconds":"14402"},"empty":{},"timestamp":{"seconds":"1704860400"},"double_value":{"value":123456789.12345679},"float_value":{"value":123456790},"int64_value":{"value":"123456789"},"uint64_value":{"value":"123456789"},"int32_value":{"value":123456789},"uint32_value":{"value":123456789},"bool_value":{"value":true},"string_value":{"value":"String marshalling and unmarshalling test"},"bytes_value":{"value":"Qnl0ZXMgbWFyc2hhbGxpbmcgYW5kIHVubWFyc2hhbGxpbmcgdGVzdA=="}}` + var expected = `{"any":{"@type":"cool.apps/test-value","value":"14402s"},"duration":"14402s","empty":{},"timestamp":"2024-01-10T04:20:00Z","double_value":123456789.12345679,"float_value":123456792,"int64_value":"123456789","uint64_value":"123456789","int32_value":"123456789","uint32_value":"123456789","bool_value":true,"string_value":"String marshalling and unmarshalling test","bytes_value":"Qnl0ZXMgbWFyc2hhbGxpbmcgYW5kIHVubWFyc2hhbGxpbmcgdGVzdA=="}` require.Equal(t, expected, string(jdata)) + + jparsed := &MessageWithWKT{} + umc := json.UnmarshalerConfig{ + AnyTypeResolver: anyTypeResolver, + } + err = umc.Unmarshal(jdata, jparsed) + require.NoError(t, err) + require.True(t, jparsed.EqualVT(m)) } diff --git a/types/known/anypb/any.go b/types/known/anypb/any.go index ed60bb98..be39bcb5 100644 --- a/types/known/anypb/any.go +++ b/types/known/anypb/any.go @@ -2,6 +2,11 @@ package anypb import ( protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" + "github.com/aperturerobotics/protobuf-go-lite/json" + anypb_resolver "github.com/aperturerobotics/protobuf-go-lite/types/known/anypb/resolver" + "github.com/aperturerobotics/protobuf-go-lite/types/known/durationpb" + "github.com/aperturerobotics/protobuf-go-lite/types/known/structpb" + "github.com/aperturerobotics/protobuf-go-lite/types/known/timestamppb" "github.com/pkg/errors" ) @@ -11,17 +16,10 @@ import ( // if no error is encountered. // // The [Types] type implements this interface. -type MessageTypeResolver interface { - // FindMessageByURL looks up a message by a URL identifier. - // See documentation on google.protobuf.Any.type_url for the URL format. - // - // Returns the constructor for the message. - // This returns (nil, ErrNotFound) if not found. - FindMessageByURL(url string) (func() protobuf_go_lite.Message, error) -} +type MessageTypeResolver = anypb_resolver.AnyTypeResolver // ErrNotFound is returned if the message type was not found. -var ErrNotFound = errors.New("proto type not found") +var ErrNotFound = errors.New("message type not found in Any") // New marshals src into a new Any instance. func New(src protobuf_go_lite.Message, typeURL string) (*Any, error) { @@ -119,3 +117,127 @@ func (x *Any) UnmarshalTo(m protobuf_go_lite.Message, typeURL string) error { func (x *Any) UnmarshalNew(typeURL string, resolver MessageTypeResolver) (protobuf_go_lite.Message, error) { return UnmarshalNew(x, typeURL, resolver) } + +// MarshalJSON marshals the Any to JSON. +func (x *Any) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Any from JSON. +func (x *Any) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// MarshalProtoJSON marshals an Any WKT. +// UnmarshalProtoJSON unmarshals an Any WKT. +func (x *Any) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + + // Read the raw object and create a sub-unmarshaler for it. + data := s.ReadRawMessage() + if s.Err() != nil { + return + } + sub := s.Sub(data) + + // Read the first field in the object. This should be @type. + if key := sub.ReadObjectField(); key != "@type" { + s.SetErrorf("first field in Any is not @type, but %q", key) + return + } + typeURL := sub.ReadString() + if err := sub.Err(); err != nil { + return + } + + // Find the message type by the type URL. + t, err := s.AnyTypeResolver().FindMessageByURL(typeURL) + if err != nil { + s.SetError(err) + return + } + + // Allocate a new message of that type. + msg := t() + if msg == nil { + s.SetError(ErrNotFound) + return + } + + var unmarshaler json.Unmarshaler + switch msgt := msg.(type) { + default: + s.SetError(ErrNotFound) + return + case *durationpb.Duration, + *structpb.Struct, + *structpb.Value, + *structpb.ListValue, + *timestamppb.Timestamp: + if field := sub.ReadObjectField(); field != "value" { + s.SetErrorf("unexpected %q field in Any", field) + return + } + unmarshaler = msgt.(json.Unmarshaler) + case json.Unmarshaler: + // Create another sub-unmarshaler for the raw data and unmarshal the message. + sub = s.Sub(data) + } + + unmarshaler.UnmarshalProtoJSON(sub) + if err := sub.Err(); err != nil { + return + } + + if field := sub.ReadObjectField(); field != "" { + s.SetErrorf("unexpected %q field in Any", field) + return + } + + // Wrap the unmarshaled message in an Any and return that. + n, err := New(msg, typeURL) + if err != nil { + sub.SetError(err) + return + } else { + *x = *n + } +} + +// MarshalProtoJSON marshals an Any WKT. +func (x *Any) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + + s.WriteObjectStart() + s.WriteObjectField("@type") + s.WriteString(x.GetTypeUrl()) + + mt, err := s.AnyTypeResolver().FindMessageByURL(x.GetTypeUrl()) + if err != nil { + s.SetError(err) + return + } + + msg := mt() + if err := x.UnmarshalTo(msg, x.GetTypeUrl()); err != nil { + s.SetError(err) + return + } + + s.WriteMore() + s.WriteObjectField("value") + + switch m := msg.(type) { + case json.Marshaler: + m.MarshalProtoJSON(s) + default: + s.SetError(errors.New("message in Any does not implement json.Marshaler")) + } + + s.WriteObjectEnd() +} diff --git a/types/known/anypb/any.pb.go b/types/known/anypb/any.pb.go index 53fc0033..66a517f0 100644 --- a/types/known/anypb/any.pb.go +++ b/types/known/anypb/any.pb.go @@ -9,7 +9,6 @@ import ( unsafe "unsafe" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" errors "github.com/pkg/errors" ) @@ -227,33 +226,6 @@ func (this *Any) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the Any message to JSON. -func (x *Any) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.TypeUrl != "" || s.HasField("type_url") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("type_url") - s.WriteString(x.TypeUrl) - } - if len(x.Value) > 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteBytes(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Any to JSON. -func (x *Any) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *Any) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/anypb/any_test.go b/types/known/anypb/any_test.go deleted file mode 100644 index e2704b87..00000000 --- a/types/known/anypb/any_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package anypb_test - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/testing/protocmp" - - apb "google.golang.org/protobuf/types/known/anypb" - epb "google.golang.org/protobuf/types/known/emptypb" - wpb "google.golang.org/protobuf/types/known/wrapperspb" -) - -func mustMarshal(m proto.Message) []byte { - b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(m) - if err != nil { - panic(err) - } - return b -} - -func TestMessage(t *testing.T) { - tests := []struct { - inAny *apb.Any - inTarget proto.Message - wantIs bool - wantName protoreflect.FullName - }{{ - inAny: nil, - inTarget: nil, - wantIs: false, - wantName: "", - }, { - inAny: new(apb.Any), - inTarget: nil, - wantIs: false, - wantName: "", - }} - - for _, tt := range tests { - gotIs := tt.inAny.MessageIs(tt.inTarget) - if gotIs != tt.wantIs { - t.Errorf("MessageIs(%v, %v) = %v, want %v", tt.inAny, tt.inTarget, gotIs, tt.wantIs) - } - gotName := tt.inAny.MessageName() - if gotName != tt.wantName { - t.Errorf("MessageName(%v) = %v, want %v", tt.inAny, gotName, tt.wantName) - } - } -} - -func TestRoundtrip(t *testing.T) { - tests := []struct { - msg proto.Message - any *apb.Any - }{{ - msg: &wpb.StringValue{Value: ""}, - any: &apb.Any{ - TypeUrl: "type.googleapis.com/google.protobuf.StringValue", - }, - }, { - msg: wpb.String("hello, world"), - any: &apb.Any{ - TypeUrl: "type.googleapis.com/google.protobuf.StringValue", - Value: mustMarshal(wpb.String("hello, world")), - }, - }, { - msg: &apb.Any{ - TypeUrl: "type.googleapis.com/google.protobuf.StringValue", - Value: mustMarshal(wpb.String("hello, world")), - }, - any: &apb.Any{ - TypeUrl: "type.googleapis.com/google.protobuf.Any", - Value: mustMarshal(&apb.Any{ - TypeUrl: "type.googleapis.com/google.protobuf.StringValue", - Value: mustMarshal(wpb.String("hello, world")), - }), - }, - }} - - for _, tt := range tests { - // Unmarshal to the wrong message type. - var empty epb.Empty - if err := tt.any.UnmarshalTo(&empty); err == nil { - t.Errorf("UnmarshalTo(empty) = nil, want non-nil") - } - - gotAny := new(apb.Any) - if err := gotAny.MarshalFrom(tt.msg); err != nil { - t.Errorf("MarshalFrom() error: %v", err) - } - if diff := cmp.Diff(tt.any, gotAny, protocmp.Transform()); diff != "" { - t.Errorf("MarshalFrom() output mismatch (-want +got):\n%s", diff) - } - - gotPB := tt.msg.ProtoReflect().New().Interface() - if err := tt.any.UnmarshalTo(gotPB); err != nil { - t.Errorf("UnmarshalTo() error: %v", err) - } - if diff := cmp.Diff(tt.msg, gotPB, protocmp.Transform()); diff != "" { - t.Errorf("UnmarshalTo() output mismatch (-want +got):\n%s", diff) - } - - gotPB, err := tt.any.UnmarshalNew() - if err != nil { - t.Errorf("UnmarshalNew() error: %v", err) - } - if diff := cmp.Diff(tt.msg, gotPB, protocmp.Transform()); diff != "" { - t.Errorf("UnmarshalNew() output mismatch (-want +got):\n%s", diff) - } - } -} diff --git a/types/known/anypb/resolver/resolver.go b/types/known/anypb/resolver/resolver.go new file mode 100644 index 00000000..4aa86b6a --- /dev/null +++ b/types/known/anypb/resolver/resolver.go @@ -0,0 +1,58 @@ +package anypb_resolver + +import ( + "errors" + + protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" +) + +// ErrNoAnyTypeResolver is returned if no resolver was provided for the Any type. +var ErrNoAnyTypeResolver = errors.New("no resolver provided for the Any type") + +// AnyTypeResolver is an interface for looking up messages. +// +// A compliant implementation must deterministically return the same type +// if no error is encountered. +// +// The [Types] type implements this interface. +type AnyTypeResolver interface { + // FindMessageByURL looks up a message by a URL identifier. + // See documentation on google.protobuf.Any.type_url for the URL format. + // + // Returns the constructor for the message. + // This returns (nil, ErrNotFound) if not found. + FindMessageByURL(url string) (func() protobuf_go_lite.Message, error) +} + +// errAnyTypeResolver implements AnyTypeResolver returning an error. +type errAnyTypeResolver struct { + err error +} + +// FindMessageByURL looks up a message by a URL identifier. +func (e *errAnyTypeResolver) FindMessageByURL(url string) (func() protobuf_go_lite.Message, error) { + return nil, e.err +} + +// NewErrAnyTypeResolver constructs a new AnyTypeResolver that returns an error. +func NewErrAnyTypeResolver(err error) AnyTypeResolver { + return &errAnyTypeResolver{err: err} +} + +// funcAnyTypeResolver implements AnyTypeResolver with callbacks +type funcAnyTypeResolver struct { + findMessageByURL func(url string) (func() protobuf_go_lite.Message, error) +} + +// NewFuncAnyTypeResolver constructs a new AnyTypeResolver with callback funcs. +func NewFuncAnyTypeResolver(findMessageByURL func(url string) (func() protobuf_go_lite.Message, error)) AnyTypeResolver { + return &funcAnyTypeResolver{findMessageByURL: findMessageByURL} +} + +// FindMessageByURL looks up a message by a URL identifier. +func (e *funcAnyTypeResolver) FindMessageByURL(url string) (func() protobuf_go_lite.Message, error) { + if e.findMessageByURL == nil { + return nil, nil + } + return e.findMessageByURL(url) +} diff --git a/types/known/apipb/api.go b/types/known/apipb/api.go new file mode 100644 index 00000000..3c07807d --- /dev/null +++ b/types/known/apipb/api.go @@ -0,0 +1 @@ +package apipb diff --git a/types/known/apipb/api.pb.go b/types/known/apipb/api.pb.go index 0398266e..317c3f2e 100644 --- a/types/known/apipb/api.pb.go +++ b/types/known/apipb/api.pb.go @@ -9,7 +9,6 @@ import ( unsafe "unsafe" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" sourcecontextpb "github.com/aperturerobotics/protobuf-go-lite/types/known/sourcecontextpb" typepb "github.com/aperturerobotics/protobuf-go-lite/types/known/typepb" errors "github.com/pkg/errors" @@ -568,159 +567,6 @@ func (this *Mixin) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the Api message to JSON. -func (x *Api) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if len(x.Methods) > 0 || s.HasField("methods") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("methods") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Methods { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("methods")) - } - s.WriteArrayEnd() - } - if len(x.Options) > 0 || s.HasField("options") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("options") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Options { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("options")) - } - s.WriteArrayEnd() - } - if x.Version != "" || s.HasField("version") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("version") - s.WriteString(x.Version) - } - if x.SourceContext != nil || s.HasField("source_context") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("source_context") - x.SourceContext.MarshalProtoJSON(s.WithField("source_context")) - } - if len(x.Mixins) > 0 || s.HasField("mixins") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("mixins") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Mixins { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("mixins")) - } - s.WriteArrayEnd() - } - if x.Syntax != 0 || s.HasField("syntax") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("syntax") - x.Syntax.MarshalProtoJSON(s) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Api to JSON. -func (x *Api) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Method message to JSON. -func (x *Method) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if x.RequestTypeUrl != "" || s.HasField("request_type_url") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("request_type_url") - s.WriteString(x.RequestTypeUrl) - } - if x.RequestStreaming || s.HasField("request_streaming") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("request_streaming") - s.WriteBool(x.RequestStreaming) - } - if x.ResponseTypeUrl != "" || s.HasField("response_type_url") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("response_type_url") - s.WriteString(x.ResponseTypeUrl) - } - if x.ResponseStreaming || s.HasField("response_streaming") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("response_streaming") - s.WriteBool(x.ResponseStreaming) - } - if len(x.Options) > 0 || s.HasField("options") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("options") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Options { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("options")) - } - s.WriteArrayEnd() - } - if x.Syntax != 0 || s.HasField("syntax") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("syntax") - x.Syntax.MarshalProtoJSON(s) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Method to JSON. -func (x *Method) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Mixin message to JSON. -func (x *Mixin) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if x.Root != "" || s.HasField("root") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("root") - s.WriteString(x.Root) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Mixin to JSON. -func (x *Mixin) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *Api) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/durationpb/duration.go b/types/known/durationpb/duration.go index 64f1fb6d..3e88ccad 100644 --- a/types/known/durationpb/duration.go +++ b/types/known/durationpb/duration.go @@ -3,8 +3,20 @@ package durationpb import ( "strconv" "strings" + + "github.com/aperturerobotics/protobuf-go-lite/json" ) +// MarshalJSON marshals the Duration to JSON. +func (x *Duration) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Duration from JSON. +func (x *Duration) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + // String formats the duration to a string. func (d *Duration) String() string { var out strings.Builder @@ -22,3 +34,24 @@ func (d *Duration) String() string { } return out.String() } + +// UnmarshalProtoJSON unmarshals a Duration from JSON. +func (x *Duration) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + d := s.ReadDuration() + if s.Err() != nil { + return + } + *x = *New(*d) +} + +// MarshalProtoJSON marshals a Duration to JSON. +func (x *Duration) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteDuration(x.AsDuration()) +} diff --git a/types/known/durationpb/duration.pb.go b/types/known/durationpb/duration.pb.go index be3ec3d0..bc6e7d50 100644 --- a/types/known/durationpb/duration.pb.go +++ b/types/known/durationpb/duration.pb.go @@ -10,7 +10,6 @@ import ( time "time" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" errors "github.com/pkg/errors" ) @@ -262,33 +261,6 @@ func (this *Duration) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the Duration message to JSON. -func (x *Duration) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Seconds != 0 || s.HasField("seconds") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("seconds") - s.WriteInt64(x.Seconds) - } - if x.Nanos != 0 || s.HasField("nanos") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("nanos") - s.WriteInt32(x.Nanos) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Duration to JSON. -func (x *Duration) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *Duration) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/emptypb/empty.go b/types/known/emptypb/empty.go new file mode 100644 index 00000000..e8cb2536 --- /dev/null +++ b/types/known/emptypb/empty.go @@ -0,0 +1,33 @@ +package emptypb + +import "github.com/aperturerobotics/protobuf-go-lite/json" + +// MarshalJSON marshals the Empty to JSON. +func (x *Empty) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Empty from JSON. +func (x *Empty) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals an Empty from JSON. +func (x *Empty) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + s.ReadObject(func(key string) { + s.SetErrorf("unexpected key %q in Empty", key) + }) + if s.Err() != nil { + return + } + *x = Empty{} +} + +// MarshalProtoJSON marshals an Empty to JSON. +func (x *Empty) MarshalProtoJSON(s *json.MarshalState) { + s.WriteObjectStart() + s.WriteObjectEnd() +} diff --git a/types/known/emptypb/empty.pb.go b/types/known/emptypb/empty.pb.go index 49c9a8a2..3c4050b1 100644 --- a/types/known/emptypb/empty.pb.go +++ b/types/known/emptypb/empty.pb.go @@ -8,7 +8,6 @@ import ( io "io" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" errors "github.com/pkg/errors" ) @@ -91,22 +90,6 @@ func (this *Empty) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the Empty message to JSON. -func (x *Empty) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Empty to JSON. -func (x *Empty) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *Empty) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/sourcecontextpb/source_context.pb.go b/types/known/sourcecontextpb/source_context.pb.go index a8657c89..b6b8cc8c 100644 --- a/types/known/sourcecontextpb/source_context.pb.go +++ b/types/known/sourcecontextpb/source_context.pb.go @@ -9,7 +9,6 @@ import ( unsafe "unsafe" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" errors "github.com/pkg/errors" ) @@ -101,28 +100,6 @@ func (this *SourceContext) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the SourceContext message to JSON. -func (x *SourceContext) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.FileName != "" || s.HasField("file_name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("file_name") - s.WriteString(x.FileName) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the SourceContext to JSON. -func (x *SourceContext) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *SourceContext) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/structpb/struct.go b/types/known/structpb/struct.go new file mode 100644 index 00000000..5482f1e9 --- /dev/null +++ b/types/known/structpb/struct.go @@ -0,0 +1,117 @@ +package structpb + +import ( + "errors" + + "github.com/aperturerobotics/protobuf-go-lite/json" +) + +// ErrJSONNotSupported is returned when JSON marshaling or unmarshaling is unsupported +var ErrJSONNotSupported = errors.New("JSON marshal/unmarshal is not supported for Struct") + +// MarshalJSON marshals the Struct to JSON. +func (x *Struct) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Struct from JSON. +func (x *Struct) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a Struct from JSON. +func (x *Struct) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + // The Struct type is not yet supported. + s.SetError(ErrJSONNotSupported) +} + +// MarshalProtoJSON marshals a Struct to JSON. +func (x *Struct) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + // The Struct type is not yet supported. + s.SetError(ErrJSONNotSupported) +} + +// MarshalJSON marshals the Value to JSON. +func (x *Value) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Value from JSON. +func (x *Value) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// MarshalProtoJSON marshals a Value to JSON. +func (x *Value) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + // The Value type is not yet supported. + s.SetError(ErrJSONNotSupported) +} + +// UnmarshalProtoJSON marshals a Struct to JSON. +func (x *Value) UnmarshalProtoJSON(s *json.UnmarshalState) { + // The Struct type is not yet supported. + s.SetError(ErrJSONNotSupported) +} + +// MarshalJSON marshals the ListValue to JSON. +func (x *ListValue) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the ListValue from JSON. +func (x *ListValue) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// MarshalProtoJSON marshals a ListValue to JSON. +func (x *ListValue) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + // The ListValue type is not yet supported. + s.SetError(ErrJSONNotSupported) +} + +// UnmarshalProtoJSON marshals a ListValue to JSON. +func (x *ListValue) UnmarshalProtoJSON(s *json.UnmarshalState) { + // The ListValue type is not supported. + s.SetError(ErrJSONNotSupported) +} + +// MarshalJSON marshals the NullValue to JSON. +func (x *NullValue) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the NullValue from JSON. +func (x *NullValue) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// MarshalProtoJSON marshals a NullValue to JSON. +func (x *NullValue) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + // The NullValue type is not yet supported. + s.SetError(ErrJSONNotSupported) +} + +// UnmarshalProtoJSON marshals a NullValue to JSON. +func (x *NullValue) UnmarshalProtoJSON(s *json.UnmarshalState) { + // The NullValue type is not supported. + s.SetError(ErrJSONNotSupported) +} diff --git a/types/known/structpb/struct.pb.go b/types/known/structpb/struct.pb.go index 74da2a47..b794c458 100644 --- a/types/known/structpb/struct.pb.go +++ b/types/known/structpb/struct.pb.go @@ -14,7 +14,6 @@ import ( unsafe "unsafe" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" errors "github.com/pkg/errors" ) @@ -803,147 +802,6 @@ func (this *ListValue) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the NullValue to JSON. -func (x NullValue) MarshalProtoJSON(s *json.MarshalState) { - s.WriteEnumString(int32(x), NullValue_name) -} - -// MarshalText marshals the NullValue to text. -func (x NullValue) MarshalText() ([]byte, error) { - return []byte(json.GetEnumString(int32(x), NullValue_name)), nil -} - -// MarshalJSON marshals the NullValue to JSON. -func (x NullValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Struct_FieldsEntry message to JSON. -func (x *Struct_FieldsEntry) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Key != "" || s.HasField("key") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("key") - s.WriteString(x.Key) - } - if x.Value != nil || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - x.Value.MarshalProtoJSON(s.WithField("value")) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Struct_FieldsEntry to JSON. -func (x *Struct_FieldsEntry) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Struct message to JSON. -func (x *Struct) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Fields != nil || s.HasField("fields") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("fields") - s.WriteObjectStart() - var wroteElement bool - for k, v := range x.Fields { - s.WriteMoreIf(&wroteElement) - s.WriteObjectStringField(k) - v.MarshalProtoJSON(s.WithField("fields")) - } - s.WriteObjectEnd() - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Struct to JSON. -func (x *Struct) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Value message to JSON. -func (x *Value) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Kind != nil { - switch ov := x.Kind.(type) { - case *Value_NullValue: - s.WriteMoreIf(&wroteField) - s.WriteObjectField("null_value") - ov.NullValue.MarshalProtoJSON(s) - case *Value_NumberValue: - s.WriteMoreIf(&wroteField) - s.WriteObjectField("number_value") - s.WriteFloat64(ov.NumberValue) - case *Value_StringValue: - s.WriteMoreIf(&wroteField) - s.WriteObjectField("string_value") - s.WriteString(ov.StringValue) - case *Value_BoolValue: - s.WriteMoreIf(&wroteField) - s.WriteObjectField("bool_value") - s.WriteBool(ov.BoolValue) - case *Value_StructValue: - s.WriteMoreIf(&wroteField) - s.WriteObjectField("struct_value") - ov.StructValue.MarshalProtoJSON(s.WithField("struct_value")) - case *Value_ListValue: - s.WriteMoreIf(&wroteField) - s.WriteObjectField("list_value") - ov.ListValue.MarshalProtoJSON(s.WithField("list_value")) - } - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Value to JSON. -func (x *Value) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the ListValue message to JSON. -func (x *ListValue) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if len(x.Values) > 0 || s.HasField("values") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("values") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Values { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("values")) - } - s.WriteArrayEnd() - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the ListValue to JSON. -func (x *ListValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *Struct) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/timestamppb/timestamp.go b/types/known/timestamppb/timestamp.go index bb237d59..b096345e 100644 --- a/types/known/timestamppb/timestamp.go +++ b/types/known/timestamppb/timestamp.go @@ -3,8 +3,41 @@ package timestamppb import ( "strconv" "strings" + + "github.com/aperturerobotics/protobuf-go-lite/json" ) +// MarshalJSON marshals the Timestamp to JSON. +func (x *Timestamp) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Timestamp from JSON. +func (x *Timestamp) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a Timestamp from JSON. +func (x *Timestamp) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + t := s.ReadTime() + if s.Err() != nil { + return + } + *x = *New(*t) +} + +// MarshalProtoJSON marshals a Timestamp to JSON. +func (x *Timestamp) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteTime(x.AsTime()) +} + // String formats the timestamp to a string. func (t *Timestamp) String() string { var out strings.Builder diff --git a/types/known/timestamppb/timestamp.pb.go b/types/known/timestamppb/timestamp.pb.go index bfc73f4e..922c88ef 100644 --- a/types/known/timestamppb/timestamp.pb.go +++ b/types/known/timestamppb/timestamp.pb.go @@ -9,7 +9,6 @@ import ( time "time" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" errors "github.com/pkg/errors" ) @@ -272,33 +271,6 @@ func (this *Timestamp) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the Timestamp message to JSON. -func (x *Timestamp) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Seconds != 0 || s.HasField("seconds") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("seconds") - s.WriteInt64(x.Seconds) - } - if x.Nanos != 0 || s.HasField("nanos") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("nanos") - s.WriteInt32(x.Nanos) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Timestamp to JSON. -func (x *Timestamp) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *Timestamp) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/typepb/type.pb.go b/types/known/typepb/type.pb.go index 09d3a711..a0e3b644 100644 --- a/types/known/typepb/type.pb.go +++ b/types/known/typepb/type.pb.go @@ -10,7 +10,6 @@ import ( unsafe "unsafe" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" anypb "github.com/aperturerobotics/protobuf-go-lite/types/known/anypb" sourcecontextpb "github.com/aperturerobotics/protobuf-go-lite/types/known/sourcecontextpb" errors "github.com/pkg/errors" @@ -952,308 +951,6 @@ func (this *Option) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the Syntax to JSON. -func (x Syntax) MarshalProtoJSON(s *json.MarshalState) { - s.WriteEnumString(int32(x), Syntax_name) -} - -// MarshalText marshals the Syntax to text. -func (x Syntax) MarshalText() ([]byte, error) { - return []byte(json.GetEnumString(int32(x), Syntax_name)), nil -} - -// MarshalJSON marshals the Syntax to JSON. -func (x Syntax) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Type message to JSON. -func (x *Type) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if len(x.Fields) > 0 || s.HasField("fields") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("fields") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Fields { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("fields")) - } - s.WriteArrayEnd() - } - if len(x.Oneofs) > 0 || s.HasField("oneofs") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("oneofs") - s.WriteStringArray(x.Oneofs) - } - if len(x.Options) > 0 || s.HasField("options") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("options") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Options { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("options")) - } - s.WriteArrayEnd() - } - if x.SourceContext != nil || s.HasField("source_context") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("source_context") - x.SourceContext.MarshalProtoJSON(s.WithField("source_context")) - } - if x.Syntax != 0 || s.HasField("syntax") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("syntax") - x.Syntax.MarshalProtoJSON(s) - } - if x.Edition != "" || s.HasField("edition") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("edition") - s.WriteString(x.Edition) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Type to JSON. -func (x *Type) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Field_Kind to JSON. -func (x Field_Kind) MarshalProtoJSON(s *json.MarshalState) { - s.WriteEnumString(int32(x), Field_Kind_name) -} - -// MarshalText marshals the Field_Kind to text. -func (x Field_Kind) MarshalText() ([]byte, error) { - return []byte(json.GetEnumString(int32(x), Field_Kind_name)), nil -} - -// MarshalJSON marshals the Field_Kind to JSON. -func (x Field_Kind) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Field_Cardinality to JSON. -func (x Field_Cardinality) MarshalProtoJSON(s *json.MarshalState) { - s.WriteEnumString(int32(x), Field_Cardinality_name) -} - -// MarshalText marshals the Field_Cardinality to text. -func (x Field_Cardinality) MarshalText() ([]byte, error) { - return []byte(json.GetEnumString(int32(x), Field_Cardinality_name)), nil -} - -// MarshalJSON marshals the Field_Cardinality to JSON. -func (x Field_Cardinality) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Field message to JSON. -func (x *Field) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Kind != 0 || s.HasField("kind") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("kind") - x.Kind.MarshalProtoJSON(s) - } - if x.Cardinality != 0 || s.HasField("cardinality") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("cardinality") - x.Cardinality.MarshalProtoJSON(s) - } - if x.Number != 0 || s.HasField("number") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("number") - s.WriteInt32(x.Number) - } - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if x.TypeUrl != "" || s.HasField("type_url") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("type_url") - s.WriteString(x.TypeUrl) - } - if x.OneofIndex != 0 || s.HasField("oneof_index") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("oneof_index") - s.WriteInt32(x.OneofIndex) - } - if x.Packed || s.HasField("packed") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("packed") - s.WriteBool(x.Packed) - } - if len(x.Options) > 0 || s.HasField("options") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("options") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Options { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("options")) - } - s.WriteArrayEnd() - } - if x.JsonName != "" || s.HasField("json_name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("json_name") - s.WriteString(x.JsonName) - } - if x.DefaultValue != "" || s.HasField("default_value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("default_value") - s.WriteString(x.DefaultValue) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Field to JSON. -func (x *Field) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Enum message to JSON. -func (x *Enum) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if len(x.Enumvalue) > 0 || s.HasField("enumvalue") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("enumvalue") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Enumvalue { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("enumvalue")) - } - s.WriteArrayEnd() - } - if len(x.Options) > 0 || s.HasField("options") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("options") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Options { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("options")) - } - s.WriteArrayEnd() - } - if x.SourceContext != nil || s.HasField("source_context") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("source_context") - x.SourceContext.MarshalProtoJSON(s.WithField("source_context")) - } - if x.Syntax != 0 || s.HasField("syntax") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("syntax") - x.Syntax.MarshalProtoJSON(s) - } - if x.Edition != "" || s.HasField("edition") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("edition") - s.WriteString(x.Edition) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Enum to JSON. -func (x *Enum) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the EnumValue message to JSON. -func (x *EnumValue) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if x.Number != 0 || s.HasField("number") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("number") - s.WriteInt32(x.Number) - } - if len(x.Options) > 0 || s.HasField("options") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("options") - s.WriteArrayStart() - var wroteElement bool - for _, element := range x.Options { - s.WriteMoreIf(&wroteElement) - element.MarshalProtoJSON(s.WithField("options")) - } - s.WriteArrayEnd() - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the EnumValue to JSON. -func (x *EnumValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Option message to JSON. -func (x *Option) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Name != "" || s.HasField("name") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("name") - s.WriteString(x.Name) - } - if x.Value != nil || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - x.Value.MarshalProtoJSON(s.WithField("value")) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Option to JSON. -func (x *Option) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *Type) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil diff --git a/types/known/wrapperspb/wrappers.go b/types/known/wrapperspb/wrappers.go new file mode 100644 index 00000000..4bb398ec --- /dev/null +++ b/types/known/wrapperspb/wrappers.go @@ -0,0 +1,295 @@ +package wrapperspb + +import ( + "strconv" + + "github.com/aperturerobotics/protobuf-go-lite/json" +) + +// MarshalJSON marshals the DoubleValue to JSON. +func (x *DoubleValue) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the DoubleValue from JSON. +func (x *DoubleValue) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a DoubleValue from JSON. +func (x *DoubleValue) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = DoubleValue{Value: s.ReadFloat64()} +} + +// MarshalProtoJSON marshals a DoubleValue to JSON. +func (x *DoubleValue) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteFloat64(x.Value) +} + +// String formats the DoubleValue to a string. +func (x *DoubleValue) String() string { + return strconv.FormatFloat(x.Value, 'g', -1, 64) +} + +// MarshalJSON marshals the FloatValue to JSON. +func (x *FloatValue) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the FloatValue from JSON. +func (x *FloatValue) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a FloatValue from JSON. +func (x *FloatValue) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = FloatValue{Value: float32(s.ReadFloat64())} +} + +// MarshalProtoJSON marshals a FloatValue to JSON. +func (x *FloatValue) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteFloat64(float64(x.Value)) +} + +// String formats the FloatValue to a string. +func (x *FloatValue) String() string { + return strconv.FormatFloat(float64(x.Value), 'g', -1, 32) +} + +// MarshalJSON marshals the Int64Value to JSON. +func (x *Int64Value) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Int64Value from JSON. +func (x *Int64Value) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a Int64Value from JSON. +func (x *Int64Value) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = Int64Value{Value: s.ReadInt64()} +} + +// MarshalProtoJSON marshals a Int64Value to JSON. +func (x *Int64Value) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteInt64(x.Value) +} + +// String formats the Int64Value to a string. +func (x *Int64Value) String() string { + return strconv.FormatInt(x.Value, 10) +} + +// MarshalJSON marshals the UInt64Value to JSON. +func (x *UInt64Value) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the UInt64Value from JSON. +func (x *UInt64Value) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a UInt64Value from JSON. +func (x *UInt64Value) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = UInt64Value{Value: s.ReadUint64()} +} + +// MarshalProtoJSON marshals a UInt64Value to JSON. +func (x *UInt64Value) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteUint64(x.Value) +} + +// String formats the UInt64Value to a string. +func (x *UInt64Value) String() string { + return strconv.FormatUint(x.Value, 10) +} + +// MarshalJSON marshals the Int32Value to JSON. +func (x *Int32Value) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the Int32Value from JSON. +func (x *Int32Value) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a Int32Value from JSON. +func (x *Int32Value) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = Int32Value{Value: int32(s.ReadInt64())} +} + +// MarshalProtoJSON marshals a Int32Value to JSON. +func (x *Int32Value) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteInt64(int64(x.Value)) +} + +// String formats the Int32Value to a string. +func (x *Int32Value) String() string { + return strconv.Itoa(int(x.Value)) +} + +// MarshalJSON marshals the UInt32Value to JSON. +func (x *UInt32Value) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the UInt32Value from JSON. +func (x *UInt32Value) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a UInt32Value from JSON. +func (x *UInt32Value) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = UInt32Value{Value: uint32(s.ReadUint64())} +} + +// MarshalProtoJSON marshals a UInt32Value to JSON. +func (x *UInt32Value) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteUint64(uint64(x.Value)) +} + +// String formats the UInt32Value to a string. +func (x *UInt32Value) String() string { + return strconv.FormatUint(uint64(x.Value), 10) +} + +// MarshalJSON marshals the BoolValue to JSON. +func (x *BoolValue) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the BoolValue from JSON. +func (x *BoolValue) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a BoolValue from JSON. +func (x *BoolValue) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = BoolValue{Value: s.ReadBool()} +} + +// MarshalProtoJSON marshals a BoolValue to JSON. +func (x *BoolValue) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteBool(x.Value) +} + +// String formats the BoolValue to a string. +func (x *BoolValue) String() string { + return strconv.FormatBool(x.Value) +} + +// MarshalJSON marshals the StringValue to JSON. +func (x *StringValue) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the StringValue from JSON. +func (x *StringValue) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a StringValue from JSON. +func (x *StringValue) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = StringValue{Value: s.ReadString()} +} + +// MarshalProtoJSON marshals a StringValue to JSON. +func (x *StringValue) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteString(x.Value) +} + +// String formats the StringValue to a string. +func (x *StringValue) String() string { + return x.Value +} + +// MarshalJSON marshals the BytesValue to JSON. +func (x *BytesValue) MarshalJSON() ([]byte, error) { + return json.DefaultMarshalerConfig.Marshal(x) +} + +// UnmarshalJSON unmarshals the BytesValue from JSON. +func (x *BytesValue) UnmarshalJSON(b []byte) error { + return json.DefaultUnmarshalerConfig.Unmarshal(b, x) +} + +// UnmarshalProtoJSON unmarshals a BytesValue from JSON. +func (x *BytesValue) UnmarshalProtoJSON(s *json.UnmarshalState) { + if s.ReadNil() { + return + } + *x = BytesValue{Value: s.ReadBytes()} +} + +// MarshalProtoJSON marshals a BytesValue to JSON. +func (x *BytesValue) MarshalProtoJSON(s *json.MarshalState) { + if x == nil { + s.WriteNil() + return + } + s.WriteBytes(x.Value) +} + +// String formats the BytesValue to a string. +func (x *BytesValue) String() string { + return string(x.Value) +} diff --git a/types/known/wrapperspb/wrappers.pb.go b/types/known/wrapperspb/wrappers.pb.go index a7cd2de9..4418afc3 100644 --- a/types/known/wrapperspb/wrappers.pb.go +++ b/types/known/wrapperspb/wrappers.pb.go @@ -11,7 +11,6 @@ import ( unsafe "unsafe" protobuf_go_lite "github.com/aperturerobotics/protobuf-go-lite" - json "github.com/aperturerobotics/protobuf-go-lite/json" errors "github.com/pkg/errors" ) @@ -626,196 +625,6 @@ func (this *BytesValue) EqualMessageVT(thatMsg any) bool { } return this.EqualVT(that) } - -// MarshalProtoJSON marshals the DoubleValue message to JSON. -func (x *DoubleValue) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value != 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteFloat64(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the DoubleValue to JSON. -func (x *DoubleValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the FloatValue message to JSON. -func (x *FloatValue) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value != 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteFloat32(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the FloatValue to JSON. -func (x *FloatValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Int64Value message to JSON. -func (x *Int64Value) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value != 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteInt64(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Int64Value to JSON. -func (x *Int64Value) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the UInt64Value message to JSON. -func (x *UInt64Value) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value != 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteUint64(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the UInt64Value to JSON. -func (x *UInt64Value) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the Int32Value message to JSON. -func (x *Int32Value) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value != 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteInt32(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the Int32Value to JSON. -func (x *Int32Value) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the UInt32Value message to JSON. -func (x *UInt32Value) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value != 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteUint32(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the UInt32Value to JSON. -func (x *UInt32Value) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the BoolValue message to JSON. -func (x *BoolValue) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteBool(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the BoolValue to JSON. -func (x *BoolValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the StringValue message to JSON. -func (x *StringValue) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if x.Value != "" || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteString(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the StringValue to JSON. -func (x *StringValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - -// MarshalProtoJSON marshals the BytesValue message to JSON. -func (x *BytesValue) MarshalProtoJSON(s *json.MarshalState) { - if x == nil { - s.WriteNil() - return - } - s.WriteObjectStart() - var wroteField bool - if len(x.Value) > 0 || s.HasField("value") { - s.WriteMoreIf(&wroteField) - s.WriteObjectField("value") - s.WriteBytes(x.Value) - } - s.WriteObjectEnd() -} - -// MarshalJSON marshals the BytesValue to JSON. -func (x *BytesValue) MarshalJSON() ([]byte, error) { - return json.DefaultMarshalerConfig.Marshal(x) -} - func (m *DoubleValue) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil