Skip to content
dogmatiqPublic

About

🚧 Opinionated Protocol Buffers enhancements for Go.

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Latest commit

 

History

236 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Primo

Opinionated Protocol Buffers enhancements for Go.

Documentation Latest Version Build Status Code Coverage

Primo is a protoc plugin that augments the Go code produced by protoc-gen-go and protoc-gen-go-grpc. It leaves the standard generated types untouched and adds extra methods and helpers alongside them, so it works with both the open and opaque APIs.

Features

Each .proto file compiled with Primo gains the following, written to a companion xxx_primo.pb.go file:

  • Field accessors — TryGet methods that report whether a one-of member is set.
  • Field mutators — fluent Set methods for each field.
  • Message builders — a fluent builder type for constructing each message.
  • Exhaustive switches — functions that switch or map over every case of a one-of group or enumeration.
  • Binary marshaling — MarshalBinary and UnmarshalBinary methods for each message.
  • Formatting — a Format method that lets a message customize its %s and %q output.
  • gRPC client stubs — test doubles for each generated gRPC client interface.

Field accessors

For each member of a one-of group, Primo generates a TryGetXxx method that returns the member's value along with a boolean reporting whether that member is the one currently set.

The accessors that protoc-gen-go generates for one-of members return only the value, leaving the caller to perform a separate type assertion on the wrapper type to discover which member is set. The TryGetXxx methods fold both steps into a single call, which reads more naturally and avoids referencing the generated wrapper types directly.

Field mutators

For each field, Primo generates a SetXxx method that assigns the field and returns the receiver, allowing calls to be chained.

These methods are generated only for open API files. The opaque API already provides SetXxx methods, so Primo does not duplicate them.

Message builders

For each message type, Primo generates a fluent builder — a XxxBuilder type with a NewXxxBuilder constructor, WithXxx methods for each field, a From method that seeds the builder from an existing message, and a Build method that returns the finished message.

Builders present a single, uniform construction API regardless of whether a message uses the open or opaque API. For open API messages the builder writes struct fields directly; for opaque API messages it uses the generated SetXxx methods.

Exhaustive switches

For each one-of group and enumeration, Primo generates functions that dispatch on the active case:

  • Switch_Xxx invokes one of a set of functions based on the current case, with a MustSwitch_Xxx variant that panics rather than tolerating an unset value.
  • Map_Xxx returns a value derived from the current case.

Because the caller must supply a function for every case, the compiler flags any call site that has not been updated after a new case is added to the .proto definition. This turns an easily missed runtime bug into a compile-time error.

Binary marshaling

For each message type, Primo generates MarshalBinary and UnmarshalBinary methods, equivalent to calling proto.Marshal and proto.Unmarshal.

These methods let each message satisfy the standard library's encoding.BinaryMarshaler and encoding.BinaryUnmarshaler interfaces, so messages can be used with any API that accepts those interfaces.

Formatting

For each message type, Primo generates a Format method that implements fmt.Formatter, taking precedence over the String method generated by protoc-gen-go.

For the %s and %q verbs, the method uses the string returned by the message's AsString method if the message provides one; otherwise it formats the message as though the method were not defined. This gives a message a place to define a human-readable representation without losing the standard Protocol Buffers formatting for the other verbs.

gRPC client stubs

For each gRPC service, Primo generates a XxxClientStub type — a test implementation of the client interface produced by protoc-gen-go-grpc.

Each stub exposes a function field for every RPC method, so a test can supply behavior for the methods it exercises and leave the rest to their default no-op implementations. This removes the boilerplate of hand-writing a client double for each service under test.

About

🚧 Opinionated Protocol Buffers enhancements for Go.

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

Generated from dogmatiq/template-go