github.com/wfusion/gofusion@v1.1.14/common/infra/watermill/components/cqrs/marshaler_protobuf.go (about)

     1  package cqrs
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/pkg/errors"
     7  	"google.golang.org/protobuf/proto"
     8  
     9  	"github.com/wfusion/gofusion/common/infra/watermill/message"
    10  	"github.com/wfusion/gofusion/common/utils"
    11  )
    12  
    13  // ProtobufMarshaler is the default Protocol Buffers marshaler.
    14  type ProtobufMarshaler struct {
    15  	NewUUID      func() string
    16  	GenerateName func(v any) string
    17  }
    18  
    19  // NoProtoMessageError is returned when the given value does not implement proto.Message.
    20  type NoProtoMessageError struct {
    21  	v any
    22  }
    23  
    24  func (e NoProtoMessageError) Error() string {
    25  	rv := reflect.ValueOf(e.v)
    26  	if rv.Kind() != reflect.Ptr {
    27  		return "v is not proto.Message, you must pass pointer value to implement proto.Message"
    28  	}
    29  
    30  	return "v is not proto.Message"
    31  }
    32  
    33  // Marshal marshals the given protobuf's message into watermill's Message.
    34  func (m ProtobufMarshaler) Marshal(v any) (*message.Message, error) {
    35  	protoMsg, ok := v.(proto.Message)
    36  	if !ok {
    37  		return nil, errors.WithStack(NoProtoMessageError{v})
    38  	}
    39  
    40  	b, err := proto.Marshal(protoMsg)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	msg := message.NewMessage(
    46  		m.newUUID(),
    47  		b,
    48  	)
    49  	msg.Metadata.Set("name", m.Name(v))
    50  
    51  	return msg, nil
    52  }
    53  
    54  func (m ProtobufMarshaler) newUUID() string {
    55  	if m.NewUUID != nil {
    56  		return m.NewUUID()
    57  	}
    58  
    59  	// default
    60  	return utils.UUID()
    61  }
    62  
    63  // Unmarshal unmarshals given watermill's Message into protobuf's message.
    64  func (ProtobufMarshaler) Unmarshal(msg *message.Message, v any) (err error) {
    65  	return proto.Unmarshal(msg.Payload, v.(proto.Message))
    66  }
    67  
    68  // Name returns the command or event's name.
    69  func (m ProtobufMarshaler) Name(cmdOrEvent any) string {
    70  	if m.GenerateName != nil {
    71  		return m.GenerateName(cmdOrEvent)
    72  	}
    73  
    74  	return FullyQualifiedStructName(cmdOrEvent)
    75  }
    76  
    77  // NameFromMessage returns the metadata name value for a given Message.
    78  func (m ProtobufMarshaler) NameFromMessage(msg *message.Message) string {
    79  	return msg.Metadata.Get("name")
    80  }