aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Borman <paul@borman.com>2018-09-09 18:38:29 -0500
committerPaul Borman <paul@borman.com>2018-09-09 18:38:29 -0500
commit16ca3eab7d2086fd5a82993a291cbf3b87fe38b7 (patch)
tree873f8e29360e8022459c5913d1b88b9e56a59f32
parente704694aed0ea004bb7eb1fc2e911d048a54606a (diff)
downloadgoogle-uuid-16ca3eab7d2086fd5a82993a291cbf3b87fe38b7.tar.gz
Add parsing support for:
{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Resolves issue #24
-rw-r--r--uuid.go61
-rw-r--r--uuid_test.go10
2 files changed, 59 insertions, 12 deletions
diff --git a/uuid.go b/uuid.go
index 920dadf..524404c 100644
--- a/uuid.go
+++ b/uuid.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Google Inc. All rights reserved.
+// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -35,20 +35,43 @@ const (
var rander = rand.Reader // random function
-// Parse decodes s into a UUID or returns an error. Both the UUID form of
-// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
-// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
+// Parse decodes s into a UUID or returns an error. Both the standard UUID
+// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
+// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
+// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
+// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
func Parse(s string) (UUID, error) {
var uuid UUID
- if len(s) != 36 {
- if len(s) != 36+9 {
- return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
- }
+ switch len(s) {
+ // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ case 36:
+
+ // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ case 36 + 9:
if strings.ToLower(s[:9]) != "urn:uuid:" {
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
}
s = s[9:]
+
+ // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ case 36 + 2:
+ s = s[1:]
+
+ // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ case 32:
+ var ok bool
+ for i := range uuid {
+ uuid[i], ok = xtob(s[i*2], s[i*2+1])
+ if !ok {
+ return uuid, errors.New("invalid UUID format")
+ }
+ }
+ return uuid, nil
+ default:
+ return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
}
+ // s is now at least 36 bytes long
+ // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
@@ -70,15 +93,29 @@ func Parse(s string) (UUID, error) {
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
var uuid UUID
- if len(b) != 36 {
- if len(b) != 36+9 {
- return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
- }
+ switch len(b) {
+ case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
}
b = b[9:]
+ case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ b = b[1:]
+ case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ var ok bool
+ for i := 0; i < 32; i += 2 {
+ uuid[i/2], ok = xtob(b[i], b[i+1])
+ if !ok {
+ return uuid, errors.New("invalid UUID format")
+ }
+ }
+ return uuid, nil
+ default:
+ return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
}
+ // s is now at least 36 bytes long
+ // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
diff --git a/uuid_test.go b/uuid_test.go
index c0a89f4..e7876f1 100644
--- a/uuid_test.go
+++ b/uuid_test.go
@@ -59,12 +59,22 @@ var tests = []test{
{"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
{"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
+
{"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
{"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
+
+
+ {"{f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, RFC4122, true},
+ {"{f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, Invalid, false},
+ {"f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, Invalid, false},
+
+ {"f47ac10b58cc037285670e02b2c3d479", 0, RFC4122, true},
+ {"f47ac10b58cc037285670e02b2c3d4790", 0, Invalid, false},
+ {"f47ac10b58cc037285670e02b2c3d47", 0, Invalid, false},
}
var constants = []struct {