Files
cof-spec/ident/member.go
Yonah 22b8cc3884 ident: isolate non-system component of member
This enables more efficient representation in contexts inherently namespaced to the current system.

Signed-off-by: Yonah <contrib@gensokyo.uk>
2026-03-22 17:33:14 +09:00

122 lines
3.2 KiB
Go

package ident
import (
"encoding/base64"
"encoding/binary"
"unsafe"
)
// PartM represents the first half of [M].
type PartM struct {
// A per-system value incremented by some unspecified amount every time the
// metadata of a member first appears to the backend.
Serial uint64
// An instant in time, some time after the corresponding member metadata
// first appeared to the backend, represented in nanoseconds since
// 1970-01-01.
Time uint64
// Randomly generated value. The implementation must guarantee that the same
// value cannot be emitted for a Time value.
ID uint64
}
// M represents a unique member identifier.
type M struct {
PartM
// Underlying system.
System S
}
func (*M) ident() {}
const (
// SizeMember is the size of the binary representation of [M].
SizeMember = SizeSystem * 2
// EncodedSizeMember is the size of the string representation of [M].
EncodedSizeMember = SizeMember / 3 * 4
)
// EncodedSize returns the number of bytes appended by Encode.
func (*M) EncodedSize() int { return EncodedSizeMember }
// Encode appends the canonical string representation of pm to dst and returns
// the extended buffer.
func (pm *PartM) Encode(dst []byte) []byte {
var buf [SizeMember - SizeSystem]byte
p := buf[:]
binary.LittleEndian.PutUint64(p, pm.Serial)
p = p[8:]
binary.LittleEndian.PutUint64(p, pm.Time)
p = p[8:]
binary.LittleEndian.PutUint64(p, pm.ID)
return base64.URLEncoding.AppendEncode(dst, buf[:])
}
// String returns the canonical string representation of pm.
func (pm *PartM) String() string {
s := pm.Encode(nil)
return unsafe.String(unsafe.SliceData(s), len(s))
}
// MarshalText returns the result of Encode.
func (pm *PartM) MarshalText() (data []byte, err error) {
return pm.Encode(nil), nil
}
// Encode appends the canonical string representation of mid to dst and returns
// the extended buffer.
func (mid *M) Encode(dst []byte) []byte {
dst = mid.PartM.Encode(dst)
return mid.System.Encode(dst)
}
// String returns the canonical string representation of mid.
func (mid *M) String() string {
s := mid.Encode(nil)
return unsafe.String(unsafe.SliceData(s), len(s))
}
// MarshalText returns the result of Encode.
func (mid *M) MarshalText() (data []byte, err error) {
return mid.Encode(nil), nil
}
// UnmarshalText strictly decodes data into pm.
func (pm *PartM) UnmarshalText(data []byte) error {
if len(data) != EncodedSizeMember-EncodedSizeSystem {
return &UnexpectedSizeError{data, EncodedSizeMember - EncodedSizeSystem}
}
var buf [SizeMember - SizeSystem]byte
if n, err := base64.URLEncoding.Decode(
buf[:],
data,
); err != nil {
return err
} else if n != SizeMember-SizeSystem {
return ErrNewline
}
p := buf[:]
pm.Serial = binary.LittleEndian.Uint64(p)
p = p[8:]
pm.Time = binary.LittleEndian.Uint64(p)
p = p[8:]
pm.ID = binary.LittleEndian.Uint64(p)
return nil
}
// UnmarshalText strictly decodes data into mid.
func (mid *M) UnmarshalText(data []byte) error {
if len(data) != EncodedSizeMember {
return &UnexpectedSizeError{data, EncodedSizeMember}
}
if err := mid.PartM.UnmarshalText(
data[:EncodedSizeMember-EncodedSizeSystem],
); err != nil {
return err
}
return mid.System.UnmarshalText(data[EncodedSizeMember-EncodedSizeSystem:])
}