github.com/ronaksoft/rony@v0.16.26-0.20230807065236-1743dbfe6959/registry/registry.go (about)

     1  package registry
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/goccy/go-json"
     7  	"google.golang.org/protobuf/encoding/protojson"
     8  	"google.golang.org/protobuf/proto"
     9  )
    10  
    11  /*
    12     Creation Time: 2020 - Aug - 27
    13     Created by:  (ehsan)
    14     Maintainers:
    15        1.  Ehsan N. Moosa (E2)
    16     Auditor: Ehsan N. Moosa (E2)
    17     Copyright Ronak Software Group 2020
    18  */
    19  
    20  // Message defines the behavior of messages in Rony. They must be able to
    21  // encode/decode ProtocolBuffer and JSON formats.
    22  type Message interface {
    23  	proto.Message
    24  	json.Marshaler
    25  	json.Unmarshaler
    26  }
    27  
    28  type Envelope interface {
    29  	GetConstructor() uint64
    30  	GetMessage() []byte
    31  }
    32  
    33  type Factory func() Message
    34  
    35  var (
    36  	constructors     = map[uint64]string{}
    37  	constructorNames = map[string]uint64{}
    38  	factories        = map[uint64]Factory{}
    39  )
    40  
    41  func Register(c uint64, n string, f Factory) {
    42  	if old, ok := constructors[c]; ok {
    43  		panic(fmt.Sprintf("constructor already exists %s:%s", old, n))
    44  	} else {
    45  		constructors[c] = n
    46  		constructorNames[n] = c
    47  	}
    48  	if f != nil {
    49  		factories[c] = f
    50  	}
    51  }
    52  
    53  func Get(c uint64) (Message, error) {
    54  	f := factories[c]
    55  	if f == nil {
    56  		return nil, errFactoryNotExists
    57  	}
    58  
    59  	return f(), nil
    60  }
    61  
    62  func Unwrap(envelope Envelope) (Message, error) {
    63  	m, err := Get(envelope.GetConstructor())
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	err = proto.UnmarshalOptions{Merge: true}.Unmarshal(envelope.GetMessage(), m)
    69  
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	return m, nil
    75  }
    76  
    77  func UnwrapJSON(envelope Envelope) (Message, error) {
    78  	m, err := Get(envelope.GetConstructor())
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	err = protojson.Unmarshal(envelope.GetMessage(), m)
    84  
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	return m, nil
    90  }
    91  
    92  func ConstructorName(c uint64) string {
    93  	return constructors[c]
    94  }
    95  
    96  func C(c uint64) string {
    97  	return constructors[c]
    98  }
    99  
   100  func ConstructorNumber(n string) uint64 {
   101  	return constructorNames[n]
   102  }
   103  
   104  func N(n string) uint64 {
   105  	return constructorNames[n]
   106  }
   107  
   108  type JSONEnvelope struct {
   109  	RequestID   uint64            `json:"requestId,omitempty"`
   110  	Header      map[string]string `json:"header,omitempty"`
   111  	Constructor string            `json:"constructor"`
   112  	Message     json.RawMessage   `json:"message,omitempty"`
   113  }
   114  
   115  var (
   116  	errFactoryNotExists = fmt.Errorf("factory not exists")
   117  )