m/p/msguid: init
Adds a new msguid package which contains functions for encoding and
decoding Microsoft's mixed-endian GUID/UUID format. This format is
used by Microsoft as well as a bunch of UEFI-related standards.
Change-Id: Icca8ef7ad7f7359808ea7f19e3824639f7b1e2eb
Reviewed-on: https://review.monogon.dev/c/monogon/+/1849
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/metropolis/pkg/msguid/BUILD.bazel b/metropolis/pkg/msguid/BUILD.bazel
new file mode 100644
index 0000000..9be5fdb
--- /dev/null
+++ b/metropolis/pkg/msguid/BUILD.bazel
@@ -0,0 +1,19 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+
+go_library(
+ name = "msguid",
+ srcs = ["msguid.go"],
+ importpath = "source.monogon.dev/metropolis/pkg/msguid",
+ visibility = ["//visibility:public"],
+ deps = ["@com_github_google_uuid//:uuid"],
+)
+
+go_test(
+ name = "msguid_test",
+ srcs = ["msguid_test.go"],
+ embed = [":msguid"],
+ deps = [
+ "@com_github_google_go_cmp//cmp",
+ "@com_github_google_uuid//:uuid",
+ ],
+)
diff --git a/metropolis/pkg/msguid/msguid.go b/metropolis/pkg/msguid/msguid.go
new file mode 100644
index 0000000..4074f8a
--- /dev/null
+++ b/metropolis/pkg/msguid/msguid.go
@@ -0,0 +1,25 @@
+// Package msguid provides functions to convert UUIDs/GUIDs to and from
+// Microsoft's idiosyncratic "mixed-endian" format.
+// See https://uefi.org/specs/UEFI/2.10/Apx_A_GUID_and_Time_Formats.html#text-representation-relationships-apxa-guid-and-time-formats
+// for an explanation of the format.
+package msguid
+
+import "github.com/google/uuid"
+
+var mixedEndianTranspose = []int{3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15}
+
+// From converts from a standard UUID into its mixed-endian encoding.
+func From(u uuid.UUID) (o [16]byte) {
+ for dest, from := range mixedEndianTranspose {
+ o[dest] = u[from]
+ }
+ return
+}
+
+// To converts a mixed-endian-encoded UUID to its standard format.
+func To(i [16]byte) (o uuid.UUID) {
+ for from, dest := range mixedEndianTranspose {
+ o[dest] = i[from]
+ }
+ return
+}
diff --git a/metropolis/pkg/msguid/msguid_test.go b/metropolis/pkg/msguid/msguid_test.go
new file mode 100644
index 0000000..b8cdfea
--- /dev/null
+++ b/metropolis/pkg/msguid/msguid_test.go
@@ -0,0 +1,40 @@
+package msguid
+
+import (
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/google/uuid"
+)
+
+func TestRoundTrip(t *testing.T) {
+ cases := []struct {
+ name string
+ uuid string
+ expected [16]byte
+ }{
+ {
+ "WikipediaExample1",
+ "00112233-4455-6677-8899-AABBCCDDEEFF",
+ [16]byte{
+ 0x33, 0x22, 0x11, 0x00, 0x55, 0x44, 0x77, 0x66,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+ },
+ },
+ }
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ origUUID := uuid.MustParse(c.uuid)
+ got := From(origUUID)
+ diff := cmp.Diff(c.expected, got)
+ if diff != "" {
+ t.Fatalf("To(%q) returned unexpected result: %v", origUUID, diff)
+ }
+ back := To(got)
+ diff2 := cmp.Diff(origUUID, back)
+ if diff2 != "" {
+ t.Errorf("From(To(%q)) did not return original value: %v", origUUID, diff2)
+ }
+ })
+ }
+}