mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-09-05 08:37:37 -04:00
guid: Improve version and variant handling
Signed-off-by: Kevin Parsons <kevpar@microsoft.com>
This commit is contained in:
+27
-3
@@ -52,10 +52,11 @@ func NewV4() (GUID, error) {
|
|||||||
return GUID{}, err
|
return GUID{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b[6] = (b[6] & 0x0f) | 0x40 // Version 4 (randomly generated)
|
g := FromArray(b)
|
||||||
b[8] = (b[8] & 0x3f) | 0x80 // RFC4122 variant
|
g.setVersion(4) // Version 4 means randomly generated.
|
||||||
|
g.setVariant(VariantRFC4122)
|
||||||
|
|
||||||
return FromArray(b), nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
|
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
|
||||||
@@ -150,6 +151,25 @@ func FromString(s string) (GUID, error) {
|
|||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GUID) setVariant(v Variant) {
|
||||||
|
d := g.Data4[0]
|
||||||
|
switch v {
|
||||||
|
case VariantNCS:
|
||||||
|
d = (d & 0x7f)
|
||||||
|
case VariantRFC4122:
|
||||||
|
d = (d & 0x3f) | 0x80
|
||||||
|
case VariantMicrosoft:
|
||||||
|
d = (d & 0x1f) | 0xc0
|
||||||
|
case VariantFuture:
|
||||||
|
d = (d & 0x0f) | 0xe0
|
||||||
|
case VariantUnknown:
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid variant: %d", v))
|
||||||
|
}
|
||||||
|
g.Data4[0] = d
|
||||||
|
}
|
||||||
|
|
||||||
// Variant returns the GUID variant, as defined in RFC 4122.
|
// Variant returns the GUID variant, as defined in RFC 4122.
|
||||||
func (g GUID) Variant() Variant {
|
func (g GUID) Variant() Variant {
|
||||||
b := g.Data4[0]
|
b := g.Data4[0]
|
||||||
@@ -165,6 +185,10 @@ func (g GUID) Variant() Variant {
|
|||||||
return VariantUnknown
|
return VariantUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GUID) setVersion(v Version) {
|
||||||
|
g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12)
|
||||||
|
}
|
||||||
|
|
||||||
// Version returns the GUID version, as defined in RFC 4122.
|
// Version returns the GUID version, as defined in RFC 4122.
|
||||||
func (g GUID) Version() Version {
|
func (g GUID) Version() Version {
|
||||||
return Version((g.Data3 & 0xF000) >> 12)
|
return Version((g.Data3 & 0xF000) >> 12)
|
||||||
|
|||||||
@@ -22,6 +22,78 @@ func mustFromString(t *testing.T, s string) GUID {
|
|||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Variant(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
g GUID
|
||||||
|
v Variant
|
||||||
|
}
|
||||||
|
testCases := []testCase{
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-0fdd-b6761fc7dcc0"), VariantNCS},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-7fdd-b6761fc7dcc0"), VariantNCS},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-bfdd-b6761fc7dcc0"), VariantRFC4122},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-9fdd-b6761fc7dcc0"), VariantRFC4122},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-cfdd-b6761fc7dcc0"), VariantMicrosoft},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-dfdd-b6761fc7dcc0"), VariantMicrosoft},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-efdd-b6761fc7dcc0"), VariantFuture},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-ffdd-b6761fc7dcc0"), VariantFuture},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
actualVariant := tc.g.Variant()
|
||||||
|
if actualVariant != tc.v {
|
||||||
|
t.Fatalf("Variant is not correct.\nExpected: %d\nActual: %d\nGUID: %s", tc.v, actualVariant, tc.g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_SetVariant(t *testing.T) {
|
||||||
|
testCases := []Variant{
|
||||||
|
VariantNCS,
|
||||||
|
VariantRFC4122,
|
||||||
|
VariantMicrosoft,
|
||||||
|
VariantFuture,
|
||||||
|
}
|
||||||
|
g := mustFromString(t, "f5cbc1a9-4cba-45a0-bfdd-b6761fc7dcc0")
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Logf("Test case: %d", tc)
|
||||||
|
g.setVariant(tc)
|
||||||
|
if g.Variant() != tc {
|
||||||
|
t.Fatalf("Variant is incorrect.\nExpected: %d\nActual: %d", tc, g.Variant())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Version(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
g GUID
|
||||||
|
v Version
|
||||||
|
}
|
||||||
|
testCases := []testCase{
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-15a0-0fdd-b6761fc7dcc0"), 1},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-25a0-0fdd-b6761fc7dcc0"), 2},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-35a0-0fdd-b6761fc7dcc0"), 3},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-45a0-0fdd-b6761fc7dcc0"), 4},
|
||||||
|
{mustFromString(t, "f5cbc1a9-4cba-55a0-0fdd-b6761fc7dcc0"), 5},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
actualVersion := tc.g.Version()
|
||||||
|
if actualVersion != tc.v {
|
||||||
|
t.Fatalf("Version is not correct.\nExpected: %d\nActual: %d\nGUID: %s", tc.v, actualVersion, tc.g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_SetVersion(t *testing.T) {
|
||||||
|
g := mustFromString(t, "f5cbc1a9-4cba-45a0-bfdd-b6761fc7dcc0")
|
||||||
|
for tc := 0; tc < 16; tc++ {
|
||||||
|
t.Logf("Test case: %d", tc)
|
||||||
|
v := Version(tc)
|
||||||
|
g.setVersion(v)
|
||||||
|
if g.Version() != v {
|
||||||
|
t.Fatalf("Version is incorrect.\nExpected: %d\nActual: %d", v, g.Version())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_NewV4IsUnique(t *testing.T) {
|
func Test_NewV4IsUnique(t *testing.T) {
|
||||||
g := mustNewV4(t)
|
g := mustNewV4(t)
|
||||||
g2 := mustNewV4(t)
|
g2 := mustNewV4(t)
|
||||||
|
|||||||
Reference in New Issue
Block a user