138 lines
2.3 KiB
Go
138 lines
2.3 KiB
Go
package domain
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"git.michelsen.id/phill/chron/chron-note/internal/util"
|
|
)
|
|
|
|
type EventType uint8
|
|
|
|
const (
|
|
EventObjectUpsert EventType = 1
|
|
EventObjectDelete EventType = 2
|
|
)
|
|
|
|
const encodingVersion uint8 = 1
|
|
|
|
type ObjectUpsert struct {
|
|
ObjectID ObjectID
|
|
Name string
|
|
Tags []string
|
|
|
|
HasBlob bool
|
|
Blob BlobID
|
|
}
|
|
|
|
type ObjectDelete struct {
|
|
ObjectID ObjectID
|
|
}
|
|
|
|
type Event struct {
|
|
Type EventType
|
|
|
|
Upsert *ObjectUpsert
|
|
Delete *ObjectDelete
|
|
}
|
|
|
|
func EncodeEvent(e Event) ([]byte, error) {
|
|
enc := util.NewEncoder(nil)
|
|
enc.U8(encodingVersion)
|
|
enc.U8(uint8(e.Type))
|
|
|
|
switch e.Type {
|
|
case EventObjectUpsert:
|
|
if e.Upsert == nil {
|
|
return nil, ErrInvalidEvent
|
|
}
|
|
u := e.Upsert
|
|
|
|
var flags uint8
|
|
if u.HasBlob {
|
|
flags |= 0x01
|
|
}
|
|
enc.U8(flags)
|
|
|
|
enc.BytesFixed(u.ObjectID[:])
|
|
enc.String(u.Name)
|
|
enc.StringSlice(u.Tags)
|
|
|
|
if u.HasBlob {
|
|
enc.BytesFixed(u.Blob[:])
|
|
}
|
|
|
|
case EventObjectDelete:
|
|
if e.Delete == nil {
|
|
return nil, ErrInvalidEvent
|
|
}
|
|
enc.BytesFixed(e.Delete.ObjectID[:])
|
|
|
|
default:
|
|
return nil, ErrUnknownEventType
|
|
}
|
|
|
|
if err := enc.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return enc.Bytes(), nil
|
|
}
|
|
|
|
func DecodeEvent(b []byte) (Event, error) {
|
|
dec := util.NewDecoder(b)
|
|
|
|
ver := dec.U8()
|
|
if dec.Err() != nil {
|
|
return Event{}, ErrDecode
|
|
}
|
|
if ver != encodingVersion {
|
|
return Event{}, fmt.Errorf("%w: unsupported encoding version %d", ErrDecode, ver)
|
|
}
|
|
|
|
typ := EventType(dec.U8())
|
|
if dec.Err() != nil {
|
|
return Event{}, ErrDecode
|
|
}
|
|
|
|
switch typ {
|
|
case EventObjectUpsert:
|
|
flags := dec.U8()
|
|
var objID ObjectID
|
|
copy(objID[:], dec.BytesFixed(len(objID)))
|
|
|
|
name := dec.String()
|
|
tags := dec.StringSlice()
|
|
|
|
hasBlob := (flags & 0x01) != 0
|
|
var blob BlobID
|
|
if hasBlob {
|
|
copy(blob[:], dec.BytesFixed(len(blob)))
|
|
}
|
|
|
|
if dec.Err() != nil {
|
|
return Event{}, ErrDecode
|
|
}
|
|
|
|
return Event{
|
|
Type: typ,
|
|
Upsert: &ObjectUpsert{
|
|
ObjectID: objID,
|
|
Name: NormalizeName(name),
|
|
Tags: NormalizeTags(tags),
|
|
HasBlob: hasBlob,
|
|
Blob: blob,
|
|
},
|
|
}, nil
|
|
|
|
case EventObjectDelete:
|
|
var objID ObjectID
|
|
copy(objID[:], dec.BytesFixed(len(objID)))
|
|
if dec.Err() != nil {
|
|
return Event{}, ErrDecode
|
|
}
|
|
return Event{Type: typ, Delete: &ObjectDelete{ObjectID: objID}}, nil
|
|
|
|
default:
|
|
return Event{}, ErrUnknownEventType
|
|
}
|
|
}
|