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 }