summaryrefslogtreecommitdiff
path: root/lib/go/thrift/uuid.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/go/thrift/uuid.go')
-rw-r--r--lib/go/thrift/uuid.go130
1 files changed, 130 insertions, 0 deletions
diff --git a/lib/go/thrift/uuid.go b/lib/go/thrift/uuid.go
new file mode 100644
index 000000000..ab47331c1
--- /dev/null
+++ b/lib/go/thrift/uuid.go
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+ "encoding/hex"
+ "fmt"
+)
+
+// Tuuid is a minimal implementation of UUID for thrift's read/write operations.
+//
+// This implementation only covers read/write in various thrift protocols.
+// If you need to generate/manipulate/etc. an UUID,
+// you likely would need a third party UUID library instead.
+//
+// This type should be directly cast-able with most popular third party UUID
+// libraries.
+// For example, assuming you are using
+// https://pkg.go.dev/github.com/google/uuid to generate a v4 UUID for an
+// optional thrift field:
+//
+// id, err := uuid.NewRandom()
+// if err != nil {
+// // TODO: handle errors
+// }
+// myRequest.Uuid = thrift.Pointer(thrift.Tuuid(id))
+type Tuuid [16]byte
+
+// String generates the canonical form string for an Tuuid.
+//
+// This string is suitable for writing with TJSONProtocol.
+func (u Tuuid) String() string {
+ var buf [36]byte
+ hex.Encode(buf[0:], u[:4])
+ buf[8] = '-'
+ hex.Encode(buf[9:], u[4:6])
+ buf[13] = '-'
+ hex.Encode(buf[14:], u[6:8])
+ buf[18] = '-'
+ hex.Encode(buf[19:], u[8:10])
+ buf[23] = '-'
+ hex.Encode(buf[24:], u[10:])
+ return string(buf[:])
+}
+
+func hexToDec(b byte) (byte, bool) {
+ switch {
+ case b >= '0' && b <= '9':
+ return b - '0', true
+ case b >= 'a' && b <= 'f':
+ return b - 'a' + 10, true
+ case b >= 'A' && b <= 'F':
+ return b - 'A' + 10, true
+ default:
+ return 0, false
+ }
+}
+
+func hexToByte(b1, b2 byte) (b byte, ok bool) {
+ b1, ok = hexToDec(b1)
+ if !ok {
+ return 0, ok
+ }
+ b2, ok = hexToDec(b2)
+ if !ok {
+ return 0, ok
+ }
+ return b1<<4 + b2, true
+}
+
+// ParseTuuid parses a canonical form UUID string into Tuuid.
+//
+// Note that this function only supports case insensitive canonical form
+// (8-4-4-4-12/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx),
+// and rejects any other forms.
+// For a more flexible UUID string parser,
+// please use third party UUID libraries.
+//
+// This function is suitable for reading with TJSONProtocol.
+func ParseTuuid(s string) (u Tuuid, err error) {
+ if len(s) != 36 || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
+ return u, fmt.Errorf("malformed Tuuid string: %q", s)
+ }
+ var ok bool
+ for i, j := range []int{
+ 0, 2, 4, 6,
+ 9, 11,
+ 14, 16,
+ 19, 21,
+ 24, 26, 28, 30, 32, 34,
+ } {
+ u[i], ok = hexToByte(s[j], s[j+1])
+ if !ok {
+ return u, fmt.Errorf("malformed Tuuid string: %q", s)
+ }
+ }
+ return u, nil
+}
+
+// Must is a sugar to be used in places that error handling is impossible (for
+// example, global variable declarations) and also errors are not in general
+// expected.
+//
+// This is an example to use Must with ParseTuuid to declare a global special
+// uuid:
+//
+// var NameSpaceDNSUUID = thrift.Must(thrift.ParseTuuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
+func Must[T any](v T, err error) T {
+ if err != nil {
+ panic(err)
+ }
+ return v
+}