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>
This commit is contained in:
@@ -117,15 +117,17 @@ func TestFM(t *testing.T) {
|
|||||||
|
|
||||||
{"valid", ident.F[ident.M, *ident.M]{
|
{"valid", ident.F[ident.M, *ident.M]{
|
||||||
I: &ident.M{
|
I: &ident.M{
|
||||||
Serial: 0xfdfdfdfdfdfdfdfd,
|
PartM: ident.PartM{
|
||||||
|
Serial: 0xfdfdfdfdfdfdfdfd,
|
||||||
|
|
||||||
Time: uint64(time.Date(
|
Time: uint64(time.Date(
|
||||||
0xfd, 7, 15,
|
0xfd, 7, 15,
|
||||||
23, 59, 59, 0xcab,
|
23, 59, 59, 0xcab,
|
||||||
time.UTC,
|
time.UTC,
|
||||||
).UnixNano()),
|
).UnixNano()),
|
||||||
|
|
||||||
ID: 0x2e736e64,
|
ID: 0x2e736e64,
|
||||||
|
},
|
||||||
|
|
||||||
System: ident.S{
|
System: ident.S{
|
||||||
Site: ident.TrivialSite,
|
Site: ident.TrivialSite,
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// M represents a unique member identifier.
|
// PartM represents the first half of [M].
|
||||||
type M struct {
|
type PartM struct {
|
||||||
// A per-system value incremented by some unspecified amount every time the
|
// A per-system value incremented by some unspecified amount every time the
|
||||||
// metadata of a member first appears to the backend.
|
// metadata of a member first appears to the backend.
|
||||||
Serial uint64
|
Serial uint64
|
||||||
@@ -18,7 +18,11 @@ type M struct {
|
|||||||
// Randomly generated value. The implementation must guarantee that the same
|
// Randomly generated value. The implementation must guarantee that the same
|
||||||
// value cannot be emitted for a Time value.
|
// value cannot be emitted for a Time value.
|
||||||
ID uint64
|
ID uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// M represents a unique member identifier.
|
||||||
|
type M struct {
|
||||||
|
PartM
|
||||||
// Underlying system.
|
// Underlying system.
|
||||||
System S
|
System S
|
||||||
}
|
}
|
||||||
@@ -35,19 +39,35 @@ const (
|
|||||||
// EncodedSize returns the number of bytes appended by Encode.
|
// EncodedSize returns the number of bytes appended by Encode.
|
||||||
func (*M) EncodedSize() int { return EncodedSizeMember }
|
func (*M) EncodedSize() int { return EncodedSizeMember }
|
||||||
|
|
||||||
// Encode appends the canonical string representation of mid to dst and returns
|
// Encode appends the canonical string representation of pm to dst and returns
|
||||||
// the extended buffer.
|
// the extended buffer.
|
||||||
func (mid *M) Encode(dst []byte) []byte {
|
func (pm *PartM) Encode(dst []byte) []byte {
|
||||||
var buf [SizeMember - SizeSystem]byte
|
var buf [SizeMember - SizeSystem]byte
|
||||||
|
|
||||||
p := buf[:]
|
p := buf[:]
|
||||||
binary.LittleEndian.PutUint64(p, mid.Serial)
|
binary.LittleEndian.PutUint64(p, pm.Serial)
|
||||||
p = p[8:]
|
p = p[8:]
|
||||||
binary.LittleEndian.PutUint64(p, mid.Time)
|
binary.LittleEndian.PutUint64(p, pm.Time)
|
||||||
p = p[8:]
|
p = p[8:]
|
||||||
binary.LittleEndian.PutUint64(p, mid.ID)
|
binary.LittleEndian.PutUint64(p, pm.ID)
|
||||||
dst = base64.URLEncoding.AppendEncode(dst, buf[:])
|
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)
|
return mid.System.Encode(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,16 +82,16 @@ func (mid *M) MarshalText() (data []byte, err error) {
|
|||||||
return mid.Encode(nil), nil
|
return mid.Encode(nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalText strictly decodes data into mid.
|
// UnmarshalText strictly decodes data into pm.
|
||||||
func (mid *M) UnmarshalText(data []byte) error {
|
func (pm *PartM) UnmarshalText(data []byte) error {
|
||||||
if len(data) != EncodedSizeMember {
|
if len(data) != EncodedSizeMember-EncodedSizeSystem {
|
||||||
return &UnexpectedSizeError{data, EncodedSizeMember}
|
return &UnexpectedSizeError{data, EncodedSizeMember - EncodedSizeSystem}
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [SizeMember - SizeSystem]byte
|
var buf [SizeMember - SizeSystem]byte
|
||||||
if n, err := base64.URLEncoding.Decode(
|
if n, err := base64.URLEncoding.Decode(
|
||||||
buf[:],
|
buf[:],
|
||||||
data[:EncodedSizeMember-EncodedSizeSystem],
|
data,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if n != SizeMember-SizeSystem {
|
} else if n != SizeMember-SizeSystem {
|
||||||
@@ -79,11 +99,23 @@ func (mid *M) UnmarshalText(data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p := buf[:]
|
p := buf[:]
|
||||||
mid.Serial = binary.LittleEndian.Uint64(p)
|
pm.Serial = binary.LittleEndian.Uint64(p)
|
||||||
p = p[8:]
|
p = p[8:]
|
||||||
mid.Time = binary.LittleEndian.Uint64(p)
|
pm.Time = binary.LittleEndian.Uint64(p)
|
||||||
p = p[8:]
|
p = p[8:]
|
||||||
mid.ID = binary.LittleEndian.Uint64(p)
|
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:])
|
return mid.System.UnmarshalText(data[EncodedSizeMember-EncodedSizeSystem:])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,48 @@ import (
|
|||||||
"git.gensokyo.uk/cofront/cof-spec/ident"
|
"git.gensokyo.uk/cofront/cof-spec/ident"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestPartM(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
rTestCases[ident.PartM, *ident.PartM]{
|
||||||
|
{"short", ident.PartM{}, nil, &ident.UnexpectedSizeError{
|
||||||
|
Data: nil,
|
||||||
|
Want: ident.EncodedSizeMember - ident.EncodedSizeSystem,
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"malformed", ident.PartM{}, []byte{
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
0xfe, 0xe1, 0xde, 0xad,
|
||||||
|
}, base64.CorruptInputError(0)},
|
||||||
|
|
||||||
|
{"newline", ident.PartM{}, []byte(
|
||||||
|
"AAAA" + strings.Repeat("\n", ident.EncodedSizeMember-ident.EncodedSizeSystem-4),
|
||||||
|
), ident.ErrNewline},
|
||||||
|
|
||||||
|
{"valid", ident.PartM{
|
||||||
|
Serial: 0xfdfdfdfdfdfdfdfd,
|
||||||
|
|
||||||
|
Time: uint64(time.Date(
|
||||||
|
0xfd, 7, 15,
|
||||||
|
23, 59, 59, 0xcab,
|
||||||
|
time.UTC,
|
||||||
|
).UnixNano()),
|
||||||
|
|
||||||
|
ID: 0x2e736e64,
|
||||||
|
}, base64.URLEncoding.AppendEncode(nil, []byte{
|
||||||
|
/* serial: */ 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
|
||||||
|
/* time: */ 0xab, 0x42, 0x42, 0xce, 0xf1, 0x92, 0x4a, 0x10,
|
||||||
|
/* id: */ 0x64, 0x6e, 0x73, 0x2e, 0, 0, 0, 0,
|
||||||
|
}), nil},
|
||||||
|
}.run(t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestM(t *testing.T) {
|
func TestM(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -43,15 +85,17 @@ func TestM(t *testing.T) {
|
|||||||
), ident.ErrNewline},
|
), ident.ErrNewline},
|
||||||
|
|
||||||
{"valid", ident.M{
|
{"valid", ident.M{
|
||||||
Serial: 0xfdfdfdfdfdfdfdfd,
|
PartM: ident.PartM{
|
||||||
|
Serial: 0xfdfdfdfdfdfdfdfd,
|
||||||
|
|
||||||
Time: uint64(time.Date(
|
Time: uint64(time.Date(
|
||||||
0xfd, 7, 15,
|
0xfd, 7, 15,
|
||||||
23, 59, 59, 0xcab,
|
23, 59, 59, 0xcab,
|
||||||
time.UTC,
|
time.UTC,
|
||||||
).UnixNano()),
|
).UnixNano()),
|
||||||
|
|
||||||
ID: 0x2e736e64,
|
ID: 0x2e736e64,
|
||||||
|
},
|
||||||
|
|
||||||
System: ident.S{
|
System: ident.S{
|
||||||
Site: ident.TrivialSite,
|
Site: ident.TrivialSite,
|
||||||
|
|||||||
Reference in New Issue
Block a user