summaryrefslogtreecommitdiff
path: root/lib/util/uuid.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util/uuid.go')
-rw-r--r--lib/util/uuid.go72
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/util/uuid.go b/lib/util/uuid.go
new file mode 100644
index 0000000..3b4cbaf
--- /dev/null
+++ b/lib/util/uuid.go
@@ -0,0 +1,72 @@
+package util
+
+import (
+ "encoding/hex"
+ "fmt"
+ "strings"
+)
+
+type UUID [16]byte
+
+func (uuid UUID) String() string {
+ str := hex.EncodeToString(uuid[:])
+ return strings.Join([]string{
+ str[:8],
+ str[8:12],
+ str[12:16],
+ str[16:20],
+ str[20:32],
+ }, "-")
+}
+
+func (a UUID) Cmp(b UUID) int {
+ for i := range a {
+ if d := int(a[i]) - int(b[i]); d != 0 {
+ return d
+ }
+ }
+ return 0
+}
+
+func (uuid UUID) Format(f fmt.State, verb rune) {
+ FormatByteArrayStringer(uuid, uuid[:], f, verb)
+}
+
+func ParseUUID(str string) (UUID, error) {
+ var ret UUID
+ j := 0
+ for i := 0; i < len(str); i++ {
+ if j >= len(ret)*2 {
+ return UUID{}, fmt.Errorf("too long to be a UUID: %q|%q", str[:i], str[i:])
+ }
+ c := str[i]
+ var v byte
+ switch {
+ case '0' <= c && c <= '9':
+ v = c - '0'
+ case 'a' <= c && c <= 'f':
+ v = c - 'a' + 10
+ case 'A' <= c && c <= 'F':
+ v = c - 'A' + 10
+ case c == '-':
+ continue
+ default:
+ return UUID{}, fmt.Errorf("illegal byte in UUID: %q|%q|%q", str[:i], str[i:i+1], str[i+1:])
+ }
+ if j%2 == 0 {
+ ret[j/2] = v << 4
+ } else {
+ ret[j/2] = (ret[j/2] & 0xf0) | (v & 0x0f)
+ }
+ j++
+ }
+ return ret, nil
+}
+
+func MustParseUUID(str string) UUID {
+ ret, err := ParseUUID(str)
+ if err != nil {
+ panic(err)
+ }
+ return ret
+}