Files

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
}
}