Last active
February 18, 2023 14:30
-
-
Save dln/41cd0dc8dca0563b8c9b9b89158ee790 to your computer and use it in GitHub Desktop.
UUID with extra encodings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package uuid | |
import ( | |
"bytes" | |
"encoding/base64" | |
"strings" | |
"github.com/gofrs/uuid/v5" | |
) | |
type UUID struct { | |
uuid.UUID | |
} | |
var ( | |
conse = [...]byte{ | |
'b', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', | |
'p', 'r', 's', 't', 'v', 'z', | |
} | |
vowse = [...]byte{'a', 'i', 'o', 'u'} | |
consd = map[byte]uint16{ | |
'b': 0, 'd': 1, 'f': 2, 'g': 3, | |
'h': 4, 'j': 5, 'k': 6, 'l': 7, | |
'm': 8, 'n': 9, 'p': 10, 'r': 11, | |
's': 12, 't': 13, 'v': 14, 'z': 15, | |
} | |
vowsd = map[byte]uint16{'a': 0, 'i': 1, 'o': 2, 'u': 3} | |
) | |
func NewV4() (UUID, error) { | |
u, err := uuid.NewV4() | |
return UUID{u}, err | |
} | |
func NewV7() (UUID, error) { | |
u, err := uuid.NewV7() | |
return UUID{u}, err | |
} | |
func (u *UUID) Base64Url() string { | |
return base64.RawURLEncoding.EncodeToString(u.Bytes()) | |
} | |
func FromBase64Url(s string) (UUID, error) { | |
b, err := base64.RawURLEncoding.DecodeString(s) | |
if err != nil { | |
return UUID{}, err | |
} | |
u, err := uuid.FromBytes(b) | |
return UUID{u}, err | |
} | |
func (u *UUID) Proquint() string { | |
var out bytes.Buffer | |
buf := u.Bytes() | |
for i := 0; i < len(buf); i = i + 2 { | |
var n uint16 = (uint16(buf[i]) * 256) + uint16(buf[i+1]) | |
var ( | |
c3 = n & 0x0f | |
v2 = (n >> 4) & 0x03 | |
c2 = (n >> 6) & 0x0f | |
v1 = (n >> 10) & 0x03 | |
c1 = (n >> 12) & 0x0f | |
) | |
out.WriteByte(conse[c1]) | |
out.WriteByte(vowse[v1]) | |
out.WriteByte(conse[c2]) | |
out.WriteByte(vowse[v2]) | |
out.WriteByte(conse[c3]) | |
if (i + 2) < len(buf) { | |
out.WriteByte('-') | |
} | |
} | |
return out.String() | |
} | |
func FromProquint(str string) (UUID, error) { | |
var ( | |
out bytes.Buffer | |
bits []string = strings.Split(str, "-") | |
) | |
for i := 0; i < len(bits); i++ { | |
var x uint16 = consd[bits[i][4]] + | |
(vowsd[bits[i][3]] << 4) + | |
(consd[bits[i][2]] << 6) + | |
(vowsd[bits[i][1]] << 10) + | |
(consd[bits[i][0]] << 12) | |
out.WriteByte(byte(x >> 8)) | |
out.WriteByte(byte(x)) | |
} | |
u, err := uuid.FromBytes(out.Bytes()) | |
if err != nil { | |
return UUID{}, err | |
} | |
return UUID{u}, nil | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package uuid | |
import ( | |
"testing" | |
"time" | |
"github.com/stretchr/testify/require" | |
) | |
func TestBase64(t *testing.T) { | |
u, err := NewV4() | |
require.NoError(t, err) | |
require.NotEmpty(t, u) | |
b64 := u.Base64Url() | |
require.Len(t, b64, 22) | |
u2, err := FromBase64Url(b64) | |
require.NoError(t, err) | |
require.Equal(t, u, u2) | |
} | |
func TestFromBase64(t *testing.T) { | |
u, err := FromBase64Url("mtmLveavS76ZAqWI4lC8sA") | |
require.NoError(t, err) | |
require.NotEmpty(t, u) | |
require.Equal(t, "9ad98bbd-e6af-4bbe-9902-a588e250bcb0", u.String()) | |
} | |
func TestV7(t *testing.T) { | |
u, _ := NewV7() | |
time.Sleep(10 * time.Millisecond) | |
u2, _ := NewV7() | |
require.Less(t, u.Base64Url(), u2.Base64Url()) | |
} | |
func TestProquint(t *testing.T) { | |
u, err := NewV4() | |
require.NoError(t, err) | |
require.NotEmpty(t, u) | |
p := u.Proquint() | |
require.Len(t, p, 47) | |
u2, err := FromProquint(p) | |
require.NoError(t, err) | |
require.Equal(t, u, u2) | |
} | |
func TestFromProquint(t *testing.T) { | |
u, err := FromProquint("ginut-sasof-rujus-hodug-nisaz-dafig-fajan-puvoh") | |
require.NoError(t, err) | |
require.Equal(t, "367dc322-bd7c-4873-970f-10932149afa4", u.String()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment