For representing full identifiers of system and member. Signed-off-by: Yonah <contrib@gensokyo.uk>
99 lines
2.6 KiB
Go
99 lines
2.6 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
|
|
}
|
|
|
|
func (*S) ident() {}
|
|
|
|
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
|
|
)
|
|
|
|
// EncodedSize returns the number of bytes appended by Encode.
|
|
func (*S) EncodedSize() int { return EncodedSizeSystem }
|
|
|
|
// 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
|
|
}
|