|
@@ -1,30 +1,55 @@
|
|
package borealis
|
|
package borealis
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "bytes"
|
|
"encoding/base64"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"encoding/json"
|
|
"fmt"
|
|
"fmt"
|
|
|
|
+ "reflect"
|
|
|
|
+
|
|
|
|
+ "github.com/fxamacker/cbor/v2"
|
|
)
|
|
)
|
|
|
|
|
|
-type Event struct {
|
|
|
|
|
|
+type Event struct { // TODO: EventEnvelope or RawEvent
|
|
Type uint16
|
|
Type uint16
|
|
TimestampS uint32
|
|
TimestampS uint32
|
|
TimestampMS uint16
|
|
TimestampMS uint16
|
|
SequentialID uint64
|
|
SequentialID uint64
|
|
UniqueID []byte
|
|
UniqueID []byte
|
|
- Payload interface{}
|
|
|
|
|
|
+ Payload map[string]interface{}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (event Event) Equal(other Event) bool {
|
|
|
|
+ if event.Type != other.Type ||
|
|
|
|
+ event.TimestampS != other.TimestampS ||
|
|
|
|
+ event.TimestampMS != other.TimestampMS ||
|
|
|
|
+ event.SequentialID != other.SequentialID ||
|
|
|
|
+ !bytes.Equal(event.UniqueID, other.UniqueID) {
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ return reflect.DeepEqual(event.Payload, other.Payload)
|
|
}
|
|
}
|
|
|
|
|
|
func (event Event) MarshalJSON() ([]byte, error) {
|
|
func (event Event) MarshalJSON() ([]byte, error) {
|
|
- array := []interface{}{
|
|
|
|
|
|
+ return json.Marshal([]interface{}{
|
|
event.Type,
|
|
event.Type,
|
|
event.TimestampS,
|
|
event.TimestampS,
|
|
event.TimestampMS,
|
|
event.TimestampMS,
|
|
event.SequentialID,
|
|
event.SequentialID,
|
|
event.UniqueID, // automatically Base64-encoded
|
|
event.UniqueID, // automatically Base64-encoded
|
|
event.Payload,
|
|
event.Payload,
|
|
- }
|
|
|
|
- return json.Marshal(array)
|
|
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (event Event) MarshalCBOR() ([]byte, error) {
|
|
|
|
+ return cbor.Marshal([]interface{}{
|
|
|
|
+ event.Type,
|
|
|
|
+ event.TimestampS,
|
|
|
|
+ event.TimestampMS,
|
|
|
|
+ event.SequentialID,
|
|
|
|
+ event.UniqueID,
|
|
|
|
+ event.Payload,
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
|
|
func (event *Event) UnmarshalJSON(input []byte) error {
|
|
func (event *Event) UnmarshalJSON(input []byte) error {
|
|
@@ -34,8 +59,9 @@ func (event *Event) UnmarshalJSON(input []byte) error {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
if len(array) != 6 {
|
|
if len(array) != 6 {
|
|
- return fmt.Errorf("event must be an array of length 6, got %d", len(array))
|
|
|
|
|
|
+ return fmt.Errorf("event must be an array of length %d, but got %d", 6, len(array))
|
|
}
|
|
}
|
|
|
|
+
|
|
event.Type = uint16(array[0].(float64))
|
|
event.Type = uint16(array[0].(float64))
|
|
event.TimestampS = uint32(array[1].(float64))
|
|
event.TimestampS = uint32(array[1].(float64))
|
|
event.TimestampMS = uint16(array[2].(float64))
|
|
event.TimestampMS = uint16(array[2].(float64))
|
|
@@ -44,6 +70,45 @@ func (event *Event) UnmarshalJSON(input []byte) error {
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
- event.Payload = array[5]
|
|
|
|
|
|
+
|
|
|
|
+ payload, ok := array[5].(map[string]interface{})
|
|
|
|
+ if !ok {
|
|
|
|
+ return fmt.Errorf("event payload must be a map")
|
|
|
|
+ }
|
|
|
|
+ event.Payload = payload
|
|
|
|
+
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (event *Event) UnmarshalCBOR(input []byte) error {
|
|
|
|
+ var err error
|
|
|
|
+ array := []interface{}{}
|
|
|
|
+ if err = cbor.Unmarshal(input, &array); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ if len(array) != 6 {
|
|
|
|
+ return fmt.Errorf("event must be an array of length %d, but got %d", 6, len(array))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ event.Type = uint16(array[0].(uint64))
|
|
|
|
+ event.TimestampS = uint32(array[1].(uint64))
|
|
|
|
+ event.TimestampMS = uint16(array[2].(uint64))
|
|
|
|
+ event.SequentialID = uint64(array[3].(uint64))
|
|
|
|
+ event.UniqueID = array[4].([]byte)
|
|
|
|
+
|
|
|
|
+ payloadIn, ok := array[5].(map[interface{}]interface{})
|
|
|
|
+ if !ok {
|
|
|
|
+ return fmt.Errorf("event payload must be a map")
|
|
|
|
+ }
|
|
|
|
+ payloadOut := make(map[string]interface{})
|
|
|
|
+ for k, v := range payloadIn {
|
|
|
|
+ var key string
|
|
|
|
+ if key, ok = k.(string); !ok {
|
|
|
|
+ return fmt.Errorf("event payload must be a map with string keys, but got the key %v", k)
|
|
|
|
+ }
|
|
|
|
+ payloadOut[key] = v
|
|
|
|
+ }
|
|
|
|
+ event.Payload = payloadOut
|
|
|
|
+
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|