protomap

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2025 License: Apache-2.0 Imports: 10 Imported by: 4

README

protomap

Protomap is a map[string]any <-> protobuf binary encoder/decoder based on protoreflect.

Like json Unmarshal/Marshal to/from generic map, but for protobuf.

Why?

To operate protobuf-encoded messages without updating generated code each time when your service need to work with tons of updated/new .proto.

How?

Mapper creates new message from descriptor every Encode/Decode call, so, it should be concurrent-safe to encode/decode multiple messages at the same time using one Mapper.

Create Mapper
protofiles := []string{/* list of .proto files, which contains messages encode/decode to */}

/* https://pkg.go.dev/github.com/bufbuild/protocompile#Compiler that will be used to compile .proto files; may be nil */
compiler := protocompile.Compiler{
    Resolver: protocompile.WithStandardImports(&protocompile.SourceResolver{}),
}

mapper, err := protomap.NewMapper(compiler, protofiles...)
if err != nil {
    panic(err)
}
Decode your message from bytes slice to map
/* full name of the message to decode */
messageName := "protomap.test.WithTimeDuration" 
result, err := mapper.Decode(binaryData, messageName)
if err != nil {
    panic(err)
}
Encode your map to bytes slice
/* full name of the message to encode */
messageName := "protomap.test.WithTimeDuration"
binaryData, err := mapper.Encode(gomap, messageName)
if err != nil {
    panic(err)
}

Interceptors

Interceptors is a functions that allows you to encode/decode custom messages to Go types, for example, time.Time <-> google.protobuf.Timestamp.

You need to pass interceptor(s) to Encode/Decode mapper methods to apply it:

messageName := "protomap.test.WithTimeDuration"
binaryData, err := mapper.Encode(gomap, messageName, interceptors.DurationEncoder, interceptors.TimeEncoder)
if err != nil {
    panic(err)
}

A few ready functions you can find in interceptors dir.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoSuchFile    = errors.New("no such file")
	ErrNoSuchMessage = errors.New("no such message in descriptor")
)

Functions

func AnyToBoolean

func AnyToBoolean(v any) (bool, error)

func AnyToBytes

func AnyToBytes(v any) ([]byte, error)

func AnyToFloat

func AnyToFloat(v any) (float64, error)

func AnyToInteger

func AnyToInteger(v any) (int64, error)

func AnyToMessage added in v0.2.0

func AnyToMessage(input any, message protoreflect.Message, inters ...EncodeInterceptor) error

func AnyToString

func AnyToString(v any) (string, error)

func AnyToUnsigned

func AnyToUnsigned(v any) (uint64, error)

func GoValueToProto

func GoValueToProto(desc protoreflect.FieldDescriptor, kind protoreflect.Kind, value any, inters ...EncodeInterceptor) (protoreflect.Value, error)

func MessageToAny added in v0.2.0

func MessageToAny(message protoreflect.Message, inters ...DecodeInterceptor) (any, error)

func ProtoToGoValue

func ProtoToGoValue(desc protoreflect.FieldDescriptor, kind protoreflect.Kind, value protoreflect.Value, inters ...DecodeInterceptor) (any, error)

Types

type DecodeInterceptor added in v0.2.0

type DecodeInterceptor func(message protoreflect.Message) (result any, applied bool, err error)

type EncodeInterceptor added in v0.2.0

type EncodeInterceptor func(input any, message protoreflect.Message) (applied bool, err error)

type Mapper

type Mapper struct {
	// contains filtered or unexported fields
}

func NewMapper

func NewMapper(compiler *protocompile.Compiler, files ...string) (*Mapper, error)

func (*Mapper) Decode

func (d *Mapper) Decode(data []byte, messageName string, inters ...DecodeInterceptor) (any, error)

func (*Mapper) Encode

func (e *Mapper) Encode(data any, messageName string, inters ...EncodeInterceptor) ([]byte, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL