Skip to content

Instantly share code, notes, and snippets.

@dln
Created February 15, 2023 10:37
Show Gist options
  • Save dln/41685941b64fe19ece8113aa6ecafdc0 to your computer and use it in GitHub Desktop.
Save dln/41685941b64fe19ece8113aa6ecafdc0 to your computer and use it in GitHub Desktop.
// Proquints: Identifiers that are Readable, Spellable, and Pronounceable
// https://arxiv.org/html/0901.4016
package main
import (
"bytes"
"fmt"
"regexp"
"strings"
"github.com/gofrs/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 IsProquint(str string) (bool, error) {
exp := "^([abdfghijklmnoprstuvz]{5}-)*[abdfghijklmnoprstuvz]{5}$"
ok, err := regexp.MatchString(exp, str)
return ok, err
}
func Encode(buf []byte) string {
var out bytes.Buffer
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 Decode(str string) []byte {
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))
}
return out.Bytes()
}
func main() {
token, _ := uuid.NewV4()
p := Encode(token.Bytes())
fmt.Printf("%v => %v => %s\n", token.Bytes(), token, p)
fmt.Printf("%s => %v\n", p, Decode(p))
fmt.Println("\nLet's make a bunch of UUIDs to show it's easier to distinguish visually.\n")
for i := 1; i <= 20; i++ {
token, _ := uuid.NewV4()
p := Encode(token.Bytes())
fmt.Printf("%s <=> %s\n", token, p)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment