From 3714aab1b26a6a1c426e33690cce13e762b24754 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 23:52:47 +0000 Subject: [PATCH 1/2] Bump github.com/dogmatiq/primo from 0.4.0 to 0.4.1 Bumps [github.com/dogmatiq/primo](https://github.com/dogmatiq/primo) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/dogmatiq/primo/releases) - [Changelog](https://github.com/dogmatiq/primo/blob/main/CHANGELOG.md) - [Commits](https://github.com/dogmatiq/primo/compare/v0.4.0...v0.4.1) --- updated-dependencies: - dependency-name: github.com/dogmatiq/primo dependency-version: 0.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 097aa36..a77ee42 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.26.0 require ( github.com/dogmatiq/dapper v0.6.1 github.com/dogmatiq/dogma v0.25.0 - github.com/dogmatiq/primo v0.4.0 + github.com/dogmatiq/primo v0.4.1 github.com/dogmatiq/spruce v0.2.4 github.com/google/go-cmp v0.7.0 go.opentelemetry.io/otel v1.46.0 diff --git a/go.sum b/go.sum index 98d3337..73a05bb 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/dogmatiq/dogma v0.25.0 h1:L1NM8xBaQMyJ+oFSKSH9FWqyQyf91I50qFN/Bz4WsT0 github.com/dogmatiq/dogma v0.25.0/go.mod h1:BNKrZq9wm3jRu35XUWQXkMRhq4EzYK+rOVbGjrbCVyI= github.com/dogmatiq/jumble v0.1.0 h1:Cb3ExfxY+AoUP4G9/sOwoOdYX8o+kOLK8+dhXAry+QA= github.com/dogmatiq/jumble v0.1.0/go.mod h1:FCGV2ImXu8zvThxhd4QLstiEdu74vbIVw9bFJSBcKr4= -github.com/dogmatiq/primo v0.4.0 h1:UcjQouSDNskd5MtB0teMCbcqpxMEtlIxZN4tpie2V24= -github.com/dogmatiq/primo v0.4.0/go.mod h1:0nluSgXdgPy+j17H/xlmngE8MOe47bLdpjaIG0sKFho= +github.com/dogmatiq/primo v0.4.1 h1:beEhEUYx1J4c9W8Ik+Gayp7XzyQYT0umrACKOs0ywQg= +github.com/dogmatiq/primo v0.4.1/go.mod h1:Do6+kOm9tWTCCAFNWrpl6VnyjmKrc67BK8KabL7vwpQ= github.com/dogmatiq/spruce v0.2.4 h1:32HqvqvlINlvMKzQ4eWO97+MdI+1CfLfr9RmsTvDphk= github.com/dogmatiq/spruce v0.2.4/go.mod h1:za5ZdNvh+FRWg4B3DCn8jfNB2LVR/9Dk3fkuHVDJLrk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= From fd8631fdb87c6d00282e5cd30405a733864754d6 Mon Sep 17 00:00:00 2001 From: James Harris Date: Mon, 28 Sep 2026 10:54:14 +1000 Subject: [PATCH 2/2] Replace hand-rolled `Format()` methods with `AsString()` and `GoString()`. --- go.mod | 2 +- go.sum | 4 +- grpc/configgrpc/config_primo.pb.go | 147 ++++++ .../messaginggrpc/commandexecutor_primo.pb.go | 293 ++++++++++++ grpc/messaginggrpc/errors_primo.pb.go | 439 ++++++++++++++++++ .../eventstreamconsumer_primo.pb.go | 366 +++++++++++++++ internal/stubs/stubs_primo.pb.go | 224 ++++++++- protobuf/configpb/config_primo.pb.go | 219 +++++++++ protobuf/envelopepb/envelope_primo.pb.go | 439 ++++++++++++++++++ protobuf/envelopepb/extensions_primo.pb.go | 74 +++ protobuf/identitypb/identity.go | 61 +-- protobuf/identitypb/identity_primo.pb.go | 74 +++ protobuf/identitypb/identity_test.go | 51 -- protobuf/uuidpb/uuid.go | 53 +-- protobuf/uuidpb/uuid_primo.pb.go | 78 +++- protobuf/uuidpb/uuid_test.go | 53 --- 16 files changed, 2378 insertions(+), 199 deletions(-) diff --git a/go.mod b/go.mod index a77ee42..c83509d 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.26.0 require ( github.com/dogmatiq/dapper v0.6.1 github.com/dogmatiq/dogma v0.25.0 - github.com/dogmatiq/primo v0.4.1 + github.com/dogmatiq/primo v0.4.3 github.com/dogmatiq/spruce v0.2.4 github.com/google/go-cmp v0.7.0 go.opentelemetry.io/otel v1.46.0 diff --git a/go.sum b/go.sum index 73a05bb..5d167c1 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/dogmatiq/dogma v0.25.0 h1:L1NM8xBaQMyJ+oFSKSH9FWqyQyf91I50qFN/Bz4WsT0 github.com/dogmatiq/dogma v0.25.0/go.mod h1:BNKrZq9wm3jRu35XUWQXkMRhq4EzYK+rOVbGjrbCVyI= github.com/dogmatiq/jumble v0.1.0 h1:Cb3ExfxY+AoUP4G9/sOwoOdYX8o+kOLK8+dhXAry+QA= github.com/dogmatiq/jumble v0.1.0/go.mod h1:FCGV2ImXu8zvThxhd4QLstiEdu74vbIVw9bFJSBcKr4= -github.com/dogmatiq/primo v0.4.1 h1:beEhEUYx1J4c9W8Ik+Gayp7XzyQYT0umrACKOs0ywQg= -github.com/dogmatiq/primo v0.4.1/go.mod h1:Do6+kOm9tWTCCAFNWrpl6VnyjmKrc67BK8KabL7vwpQ= +github.com/dogmatiq/primo v0.4.3 h1:Q6+HzBYuhLhrrwKWkgHb3MOo5JLHTneN+lgmtgGDavI= +github.com/dogmatiq/primo v0.4.3/go.mod h1:Bb1BMVwxC+adAs/Io6tACagI0OvTCGHKNQQ62YtrW1w= github.com/dogmatiq/spruce v0.2.4 h1:32HqvqvlINlvMKzQ4eWO97+MdI+1CfLfr9RmsTvDphk= github.com/dogmatiq/spruce v0.2.4/go.mod h1:za5ZdNvh+FRWg4B3DCn8jfNB2LVR/9Dk3fkuHVDJLrk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= diff --git a/grpc/configgrpc/config_primo.pb.go b/grpc/configgrpc/config_primo.pb.go index 2f88dcb..14ced0c 100644 --- a/grpc/configgrpc/config_primo.pb.go +++ b/grpc/configgrpc/config_primo.pb.go @@ -8,6 +8,7 @@ package configgrpc import ( "context" + "fmt" configpb "github.com/dogmatiq/enginekit/protobuf/configpb" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -80,6 +81,152 @@ func (b *ListApplicationsResponseBuilder) WithApplications(v []*configpb.Applica return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ListApplicationsRequest) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ListApplicationsRequest + type ListApplicationsRequest realType + fmt.Fprintf(f, format, (*ListApplicationsRequest)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ListApplicationsResponse) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ListApplicationsResponse + type ListApplicationsResponse realType + fmt.Fprintf(f, format, (*ListApplicationsResponse)(x)) +} + // ConfigAPIClientStub is a test implementation of the [ConfigAPIClient] interface. var _ ConfigAPIClient = (*ConfigAPIClientStub)(nil) diff --git a/grpc/messaginggrpc/commandexecutor_primo.pb.go b/grpc/messaginggrpc/commandexecutor_primo.pb.go index e48a340..e1b6a13 100644 --- a/grpc/messaginggrpc/commandexecutor_primo.pb.go +++ b/grpc/messaginggrpc/commandexecutor_primo.pb.go @@ -8,6 +8,7 @@ package messaginggrpc import ( "context" + "fmt" envelopepb "github.com/dogmatiq/enginekit/protobuf/envelopepb" uuidpb "github.com/dogmatiq/enginekit/protobuf/uuidpb" grpc "google.golang.org/grpc" @@ -318,6 +319,298 @@ func Map_ExecuteCommandResponse_Operation[T any]( } } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ExecuteCommandRequest) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ExecuteCommandRequest + type ExecuteCommandRequest realType + fmt.Fprintf(f, format, (*ExecuteCommandRequest)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ExecuteCommandResponse) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ExecuteCommandResponse + type ExecuteCommandResponse realType + fmt.Fprintf(f, format, (*ExecuteCommandResponse)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ExecuteCommandResponse_CommandAccepted) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ExecuteCommandResponse_CommandAccepted + type ExecuteCommandResponse_CommandAccepted realType + fmt.Fprintf(f, format, (*ExecuteCommandResponse_CommandAccepted)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ExecuteCommandResponse_EventRecorded) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ExecuteCommandResponse_EventRecorded + type ExecuteCommandResponse_EventRecorded realType + fmt.Fprintf(f, format, (*ExecuteCommandResponse_EventRecorded)(x)) +} + // CommandExecutorAPIClientStub is a test implementation of the [CommandExecutorAPIClient] interface. var _ CommandExecutorAPIClient = (*CommandExecutorAPIClientStub)(nil) diff --git a/grpc/messaginggrpc/errors_primo.pb.go b/grpc/messaginggrpc/errors_primo.pb.go index c0069e1..19b97d8 100644 --- a/grpc/messaginggrpc/errors_primo.pb.go +++ b/grpc/messaginggrpc/errors_primo.pb.go @@ -7,6 +7,7 @@ package messaginggrpc import ( + "fmt" uuidpb "github.com/dogmatiq/enginekit/protobuf/uuidpb" proto "google.golang.org/protobuf/proto" ) @@ -257,6 +258,444 @@ func (b *InvalidMessageBuilder) WithMessageTypeId(v *uuidpb.UUID) *InvalidMessag return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *UnrecognizedApplication) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = UnrecognizedApplication + type UnrecognizedApplication realType + fmt.Fprintf(f, format, (*UnrecognizedApplication)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *UnrecognizedEventStream) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = UnrecognizedEventStream + type UnrecognizedEventStream realType + fmt.Fprintf(f, format, (*UnrecognizedEventStream)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *UnrecognizedCommandType) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = UnrecognizedCommandType + type UnrecognizedCommandType realType + fmt.Fprintf(f, format, (*UnrecognizedCommandType)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *UnrecognizedEventType) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = UnrecognizedEventType + type UnrecognizedEventType realType + fmt.Fprintf(f, format, (*UnrecognizedEventType)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *MalformedMessage) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = MalformedMessage + type MalformedMessage realType + fmt.Fprintf(f, format, (*MalformedMessage)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *InvalidMessage) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = InvalidMessage + type InvalidMessage realType + fmt.Fprintf(f, format, (*InvalidMessage)(x)) +} + // MarshalBinary returns the binary representation of the message, equivalent to // calling proto.Marshal(x). // diff --git a/grpc/messaginggrpc/eventstreamconsumer_primo.pb.go b/grpc/messaginggrpc/eventstreamconsumer_primo.pb.go index 05e4aa4..e5b2089 100644 --- a/grpc/messaginggrpc/eventstreamconsumer_primo.pb.go +++ b/grpc/messaginggrpc/eventstreamconsumer_primo.pb.go @@ -8,6 +8,7 @@ package messaginggrpc import ( "context" + "fmt" envelopepb "github.com/dogmatiq/enginekit/protobuf/envelopepb" uuidpb "github.com/dogmatiq/enginekit/protobuf/uuidpb" grpc "google.golang.org/grpc" @@ -240,6 +241,371 @@ func (b *ConsumeEventsResponseBuilder) WithEnvelopes(v []*envelopepb.MultiEnvelo return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ListEventStreamsRequest) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ListEventStreamsRequest + type ListEventStreamsRequest realType + fmt.Fprintf(f, format, (*ListEventStreamsRequest)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ListEventStreamsResponse) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ListEventStreamsResponse + type ListEventStreamsResponse realType + fmt.Fprintf(f, format, (*ListEventStreamsResponse)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *EventStream) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = EventStream + type EventStream realType + fmt.Fprintf(f, format, (*EventStream)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ConsumeEventsRequest) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ConsumeEventsRequest + type ConsumeEventsRequest realType + fmt.Fprintf(f, format, (*ConsumeEventsRequest)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ConsumeEventsResponse) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ConsumeEventsResponse + type ConsumeEventsResponse realType + fmt.Fprintf(f, format, (*ConsumeEventsResponse)(x)) +} + // EventStreamConsumerAPIClientStub is a test implementation of the [EventStreamConsumerAPIClient] interface. var _ EventStreamConsumerAPIClient = (*EventStreamConsumerAPIClientStub)(nil) diff --git a/internal/stubs/stubs_primo.pb.go b/internal/stubs/stubs_primo.pb.go index 2325f21..fb09207 100644 --- a/internal/stubs/stubs_primo.pb.go +++ b/internal/stubs/stubs_primo.pb.go @@ -6,7 +6,10 @@ package stubs -import proto "google.golang.org/protobuf/proto" +import ( + "fmt" + proto "google.golang.org/protobuf/proto" +) type ProtoStubABuilder struct { prototype ProtoStubA @@ -119,6 +122,225 @@ func (b *ProtoStubCBuilder) WithValue(v string) *ProtoStubCBuilder { return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ProtoStubA) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ProtoStubA + type ProtoStubA realType + fmt.Fprintf(f, format, (*ProtoStubA)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ProtoStubB) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ProtoStubB + type ProtoStubB realType + fmt.Fprintf(f, format, (*ProtoStubB)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *ProtoStubC) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = ProtoStubC + type ProtoStubC realType + fmt.Fprintf(f, format, (*ProtoStubC)(x)) +} + // MarshalBinary returns the binary representation of the message, equivalent to // calling proto.Marshal(x). // diff --git a/protobuf/configpb/config_primo.pb.go b/protobuf/configpb/config_primo.pb.go index d56bbeb..adf9f99 100644 --- a/protobuf/configpb/config_primo.pb.go +++ b/protobuf/configpb/config_primo.pb.go @@ -344,6 +344,225 @@ func Map_HandlerType[T any]( } } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Application) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Application + type Application realType + fmt.Fprintf(f, format, (*Application)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Handler) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Handler + type Handler realType + fmt.Fprintf(f, format, (*Handler)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *MessageUsage) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = MessageUsage + type MessageUsage realType + fmt.Fprintf(f, format, (*MessageUsage)(x)) +} + // MarshalBinary returns the binary representation of the message, equivalent to // calling proto.Marshal(x). // diff --git a/protobuf/envelopepb/envelope_primo.pb.go b/protobuf/envelopepb/envelope_primo.pb.go index 38fb9b5..c55d4d6 100644 --- a/protobuf/envelopepb/envelope_primo.pb.go +++ b/protobuf/envelopepb/envelope_primo.pb.go @@ -7,6 +7,7 @@ package envelopepb import ( + "fmt" identitypb "github.com/dogmatiq/enginekit/protobuf/identitypb" uuidpb "github.com/dogmatiq/enginekit/protobuf/uuidpb" proto "google.golang.org/protobuf/proto" @@ -445,6 +446,444 @@ func (b *BodyBuilder) WithBaggage(v []*anypb.Any) *BodyBuilder { return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Envelope) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Envelope + type Envelope realType + fmt.Fprintf(f, format, (*Envelope)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *MultiEnvelope) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = MultiEnvelope + type MultiEnvelope realType + fmt.Fprintf(f, format, (*MultiEnvelope)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Source) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Source + type Source realType + fmt.Fprintf(f, format, (*Source)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Message) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Message + type Message realType + fmt.Fprintf(f, format, (*Message)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Header) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Header + type Header realType + fmt.Fprintf(f, format, (*Header)(x)) +} + +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Body) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Body + type Body realType + fmt.Fprintf(f, format, (*Body)(x)) +} + // MarshalBinary returns the binary representation of the message, equivalent to // calling proto.Marshal(x). // diff --git a/protobuf/envelopepb/extensions_primo.pb.go b/protobuf/envelopepb/extensions_primo.pb.go index 227651b..461c90d 100644 --- a/protobuf/envelopepb/extensions_primo.pb.go +++ b/protobuf/envelopepb/extensions_primo.pb.go @@ -7,6 +7,7 @@ package envelopepb import ( + "fmt" uuidpb "github.com/dogmatiq/enginekit/protobuf/uuidpb" proto "google.golang.org/protobuf/proto" ) @@ -61,6 +62,79 @@ func (b *EventStreamPositionBuilder) WithOffset(v uint64) *EventStreamPositionBu return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *EventStreamPosition) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = EventStreamPosition + type EventStreamPosition realType + fmt.Fprintf(f, format, (*EventStreamPosition)(x)) +} + // MarshalBinary returns the binary representation of the message, equivalent to // calling proto.Marshal(x). // diff --git a/protobuf/identitypb/identity.go b/protobuf/identitypb/identity.go index b0ca07d..3ec6861 100644 --- a/protobuf/identitypb/identity.go +++ b/protobuf/identitypb/identity.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "slices" - "strings" uuidpb "github.com/dogmatiq/enginekit/protobuf/uuidpb" ) @@ -111,56 +110,24 @@ func (x *Identity) UnmarshalText(text []byte) error { return x.Validate() } -// Format implements the fmt.Formatter interface, allowing identities to be -// formatted with functions from the fmt package. -func (x *Identity) Format(f fmt.State, verb rune) { - format := fmt.FormatString(f, verb) - - // If we're formatting as a string, show the UUID followed by the name. A - // question mark is used as a placeholder when the name is empty. - if verb == 's' { - name := x.GetName() - if name == "" { - name = "?" - } - - var b strings.Builder - key, _ := x.GetKey().MarshalText() - b.Write(key) - b.WriteByte(' ') - b.WriteString(name) - - fmt.Fprintf(f, format, b.String()) - return - } - - // If we're formatting the Go syntax, output something more useful than the - // protobuf internals. - if verb == 'v' && f.Flag('#') { - fmt.Fprintf( - f, - "identitypb.New(%#v, %#v)", - x.GetName(), - x.GetKey(), - ) - return +// AsString returns a human-readable representation of the identity. +func (x *Identity) AsString() string { + name := x.GetName() + if name == "" { + name = "?" } - // Otherwise, fall-back to the default behavior. In order to avoid infinite - // recursion into this method, we define a new type that does not have any - // methods. + return fmt.Sprintf("%s %s", x.GetKey(), name) - // First, we create an alias to the _real_ type so that we can base our new - // type on it without causing a recursive type definition. - type realType = Identity - - // Then, we create a new type with the structure of the real type, but none - // of its methods. We use the same name as the real type so that any format - // verbs that include the type name (such as "%T") will still print the - // correct name. - type Identity realType +} - fmt.Fprintf(f, format, (*Identity)(x)) +// GoString implements the [fmt.GoStringer] interface. +func (x *Identity) GoString() string { + return fmt.Sprintf( + "identitypb.New(%#v, %#v)", + x.GetName(), + x.GetKey(), + ) } // Equal returns true if x and id are equal. diff --git a/protobuf/identitypb/identity_primo.pb.go b/protobuf/identitypb/identity_primo.pb.go index 98a11cc..4008c4b 100644 --- a/protobuf/identitypb/identity_primo.pb.go +++ b/protobuf/identitypb/identity_primo.pb.go @@ -7,6 +7,7 @@ package identitypb import ( + "fmt" uuidpb "github.com/dogmatiq/enginekit/protobuf/uuidpb" proto "google.golang.org/protobuf/proto" ) @@ -61,6 +62,79 @@ func (b *IdentityBuilder) WithKey(v *uuidpb.UUID) *IdentityBuilder { return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *Identity) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = Identity + type Identity realType + fmt.Fprintf(f, format, (*Identity)(x)) +} + // MarshalBinary returns the binary representation of the message, equivalent to // calling proto.Marshal(x). // diff --git a/protobuf/identitypb/identity_test.go b/protobuf/identitypb/identity_test.go index f70883e..43f0914 100644 --- a/protobuf/identitypb/identity_test.go +++ b/protobuf/identitypb/identity_test.go @@ -1,7 +1,6 @@ package identitypb_test import ( - "fmt" "strings" "testing" @@ -192,56 +191,6 @@ func TestIdentity_ParseAndMustParse(t *testing.T) { }) } -func TestIdentity_Format(t *testing.T) { - t.Parallel() - - subject := New( - "", - uuidpb. - NewUUIDBuilder(). - WithUpper(0xa967a8b93f9c4918). - WithLower(0x9a4119577be5fec5). - Build(), - ) - - cases := []struct { - Desc string - Format string - Want string - }{ - { - "it formats as a UUID-prefixed string", - "%s", - `a967a8b9-3f9c-4918-9a41-19577be5fec5 `, - }, - { - "it formats as a Go constructor expression", - "%#v", - `identitypb.New("", uuidpb.MustParse("a967a8b9-3f9c-4918-9a41-19577be5fec5"))`, - }, - } - - for _, c := range cases { - t.Run(c.Desc, func(t *testing.T) { - t.Parallel() - - actual := fmt.Sprintf(c.Format, subject) - if actual != c.Want { - t.Fatalf("got %q, want %q", actual, c.Want) - } - }) - } - - t.Run("the %v verb uses the default protobuf formatting", func(t *testing.T) { - t.Parallel() - - actual := fmt.Sprintf("%v", subject) - if !strings.HasPrefix(actual, "&{") { - t.Errorf("got %q, want raw struct output", actual) - } - }) -} - func TestIdentity_MarshalText(t *testing.T) { t.Parallel() diff --git a/protobuf/uuidpb/uuid.go b/protobuf/uuidpb/uuid.go index 3d95bc5..d737b7d 100644 --- a/protobuf/uuidpb/uuid.go +++ b/protobuf/uuidpb/uuid.go @@ -303,6 +303,16 @@ func (x *UUID) AsString() string { return string(data[:]) } +// GoString implements the [fmt.GoStringer] interface. +func (x *UUID) GoString() string { + return fmt.Sprintf("uuidpb.MustParse(%q)", x.AsString()) +} + +// DapperString implements [github.com/dogmatiq/dapper.Stringer]. +func (x *UUID) DapperString() string { + return x.AsString() +} + // MarshalText implements the [encoding.TextMarshaler] interface. func (x *UUID) MarshalText() ([]byte, error) { data := asHex(x.GetUpper(), x.GetLower()) @@ -347,49 +357,6 @@ func (x *UUID) UnmarshalText(text []byte) error { return nil } -// DapperString implements [github.com/dogmatiq/dapper.Stringer]. -func (x *UUID) DapperString() string { - return x.AsString() -} - -// Format implements the [fmt.Formatter] interface, allowing UUIDs to be -// formatted with functions from the [fmt] package. -// -// This method takes precedence over the [UUID.String] method, which is -// generated by the Protocol Buffers compiler. -func (x *UUID) Format(f fmt.State, verb rune) { - format := fmt.FormatString(f, verb) - - // If we're formatting as a string, use the RFC 9562 format. - if verb == 's' || verb == 'q' { - fmt.Fprintf(f, format, x.AsString()) - return - } - - // If we're formatting the Go syntax, output something more useful than the - // protobuf internals. - if verb == 'v' && f.Flag('#') { - fmt.Fprintf(f, "uuidpb.MustParse(%q)", x.AsString()) - return - } - - // Otherwise, fall-back to the default behavior. In order to avoid infinite - // recursion into this method, we define a new type that does not have any - // methods. - - // First, we create an alias to the _real_ type so that we can base our new - // type on it without causing a recursive type definition. - type realType = UUID - - // Then, we create a new type with the structure of the real type, but none - // of its methods. We use the same name as the real type so that any format - // verbs that include the type name (such as "%T") will still print the - // correct name. - type UUID realType - - fmt.Fprintf(f, format, (*UUID)(x)) -} - // Validate returns an error if x is not a valid Version 4 (random) or Version 5 // (name-based) UUID. func (x *UUID) Validate() error { diff --git a/protobuf/uuidpb/uuid_primo.pb.go b/protobuf/uuidpb/uuid_primo.pb.go index 8816551..c13b912 100644 --- a/protobuf/uuidpb/uuid_primo.pb.go +++ b/protobuf/uuidpb/uuid_primo.pb.go @@ -6,7 +6,10 @@ package uuidpb -import proto "google.golang.org/protobuf/proto" +import ( + "fmt" + proto "google.golang.org/protobuf/proto" +) type UUIDBuilder struct { prototype UUID @@ -54,6 +57,79 @@ func (b *UUIDBuilder) WithLower(v uint64) *UUIDBuilder { return b } +// Format formats x according to the given [fmt] verb. +// +// It implements [fmt.Formatter], taking precedence over the String() method +// generated by the Protocol Buffers compiler. +// +// For the %s and %q verbs it uses the string returned by x.AsString() if x +// provides such a method. For the %#v verb it uses the string returned by +// x.GoString() if x provides such a method. Otherwise it formats x as though this +// method were not defined. +// +// AsString() and GoString() are called even when x is nil, since some message +// types handle a nil receiver themselves. If either method panics, the panic is +// formatted the same way the fmt package formats a panicking String() method. +func (x *UUID) Format(f fmt.State, verb rune) { + format := fmt.FormatString(f, verb) + + if verb == 's' || verb == 'q' { + if s, ok := any(x).(interface { + AsString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=AsString method: %v)", verb, r) + } + }() + return s.AsString(), true + }() + if ok { + fmt.Fprintf(f, format, result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } + + if verb == 'v' && f.Flag('#') { + if s, ok := any(x).(interface { + GoString() string + }); ok { + result, ok := func() (result string, ok bool) { + defer func() { + if r := recover(); r != nil { + result = fmt.Sprintf("%%!%c(PANIC=GoString method: %v)", verb, r) + } + }() + return s.GoString(), true + }() + if ok { + fmt.Fprintf(f, fmt.FormatString(f, 's'), result) + } else if x == nil { + fmt.Fprint(f, "") + } else { + fmt.Fprint(f, result) + } + return + } + } else { + switch verb { + case 'v', 's', 'x', 'X', 'q': + fmt.Fprintf(f, format, x.String()) + return + } + } + + type realType = UUID + type UUID realType + fmt.Fprintf(f, format, (*UUID)(x)) +} + // MarshalBinary returns the binary representation of the message, equivalent to // calling proto.Marshal(x). // diff --git a/protobuf/uuidpb/uuid_test.go b/protobuf/uuidpb/uuid_test.go index ae46a88..0c98807 100644 --- a/protobuf/uuidpb/uuid_test.go +++ b/protobuf/uuidpb/uuid_test.go @@ -2,8 +2,6 @@ package uuidpb_test import ( "bytes" - "fmt" - "strings" "testing" "github.com/dogmatiq/dapper" @@ -762,57 +760,6 @@ func TestUUID_DapperString(t *testing.T) { } } -func TestUUID_Format(t *testing.T) { - t.Parallel() - - subject := NewUUIDBuilder(). - WithUpper(0xa967a8b93f9c4918). - WithLower(0x9a4119577be5fec5). - Build() - - cases := []struct { - Desc string - Format string - Want string - }{ - { - "string", - "%s", - `a967a8b9-3f9c-4918-9a41-19577be5fec5`, - }, - { - "quoted string", - "%q", - `"a967a8b9-3f9c-4918-9a41-19577be5fec5"`, - }, - { - "go string", - "%#v", - `uuidpb.MustParse("a967a8b9-3f9c-4918-9a41-19577be5fec5")`, - }, - } - - for _, c := range cases { - t.Run(c.Desc, func(t *testing.T) { - t.Parallel() - - actual := fmt.Sprintf(c.Format, subject) - if actual != c.Want { - t.Fatalf("got %q, want %q", actual, c.Want) - } - }) - } - - t.Run("the %v verb uses the default protobuf formatting", func(t *testing.T) { - t.Parallel() - - actual := fmt.Sprintf("%v", subject) - if !strings.HasPrefix(actual, "&{") { - t.Errorf("got %q, want raw struct output", actual) - } - }) -} - func TestUUID_Validate(t *testing.T) { t.Parallel()