Files
cof-spec/ident/system.go
2026-03-21 21:14:32 +09:00

94 lines
2.4 KiB
Go

package ident
import (
"encoding/base64"
"encoding/binary"
"unsafe"
)
const (
// TrivialSite is conventionally reserved for the [S.Site] field on a
// trivial, single-host server implementation.
TrivialSite = 0xfeedcafe
// TrivialHost is conventionally reserved for the [S.Host] field on a
// trivial, single-host server implementation.
TrivialHost = 0xcafebabe
)
// S represents a unique system identifier.
type S struct {
// Deployment site, typically denoting a datacenter servicing a region.
Site uint32
// Servicing host behind load balancer, unique within its Site.
Host uint32
// An instant in time, some time after the corresponding system 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 on a servicing Host.
ID uint64
}
const (
// SizeSystem is the size of the binary representation of [S].
SizeSystem = 24
// EncodedSizeSystem is the size of the string representation of [S].
EncodedSizeSystem = SizeSystem / 3 * 4
)
// Encode appends the canonical string representation of sid to dst and returns
// the extended buffer.
func (sid *S) Encode(dst []byte) []byte {
var buf [SizeSystem]byte
p := buf[:]
binary.LittleEndian.PutUint32(p, sid.Site)
p = p[4:]
binary.LittleEndian.PutUint32(p, sid.Host)
p = p[4:]
binary.LittleEndian.PutUint64(p, sid.Time)
p = p[8:]
binary.LittleEndian.PutUint64(p, sid.ID)
return base64.URLEncoding.AppendEncode(dst, buf[:])
}
// String returns the canonical string representation of sid.
func (sid *S) String() string {
s := sid.Encode(nil)
return unsafe.String(unsafe.SliceData(s), len(s))
}
// MarshalText returns the result of Encode.
func (sid *S) MarshalText() (data []byte, err error) {
return sid.Encode(nil), nil
}
// UnmarshalText strictly decodes data into sid.
func (sid *S) UnmarshalText(data []byte) error {
if len(data) != EncodedSizeSystem {
return &UnexpectedSizeError{data, EncodedSizeSystem}
}
var buf [SizeSystem]byte
if n, err := base64.URLEncoding.Decode(
buf[:],
data,
); err != nil {
return err
} else if n != SizeSystem {
return ErrNewline
}
p := buf[:]
sid.Site = binary.LittleEndian.Uint32(p)
p = p[4:]
sid.Host = binary.LittleEndian.Uint32(p)
p = p[4:]
sid.Time = binary.LittleEndian.Uint64(p)
p = p[8:]
sid.ID = binary.LittleEndian.Uint64(p)
return nil
}