1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
package prototool
import (
"fmt"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)
type ProtoErrMarshaler struct {
}
func (ProtoErrMarshaler) Marshal(err error) ([]byte, error) {
e, ok := err.(proto.Message) // nolint:errorlint
if !ok {
return nil, fmt.Errorf("expected proto.Message, got %T", err) // nolint:errorlint
}
return protoMarshal(e)
}
func (ProtoErrMarshaler) Unmarshal(data []byte) (error, error) {
e, err := protoUnmarshal(data)
if err != nil {
return nil, err
}
err, ok := e.(error)
if !ok {
return nil, fmt.Errorf("expected the proto.Message to be an error but it's not: %T", e)
}
return err, nil
}
func protoMarshal(m proto.Message) ([]byte, error) {
any, err := anypb.New(m) // use Any to capture type information so that a value can be instantiated in protoUnmarshal()
if err != nil {
return nil, err
}
return proto.Marshal(any)
}
func protoUnmarshal(data []byte) (proto.Message, error) {
var any anypb.Any
err := proto.Unmarshal(data, &any)
if err != nil {
return nil, err
}
return any.UnmarshalNew()
}
|