Files
byre/internal/ids/ids.go
T

73 lines
1.6 KiB
Go

package ids
import (
"crypto/rand"
"crypto/sha256"
"encoding/binary"
"fmt"
"strings"
)
const (
alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
randomLength = 11
)
const (
Project = "prj"
Task = "tsk"
Session = "ses"
Snapshot = "snp"
Review = "rev"
InboxItem = "inb"
InboxResponse = "rsp"
Blob = "blb"
LeadNote = "not"
WorkflowDefinition = "wfd"
WorkflowRun = "run"
Send = "snd"
Client = "cli"
ClientRequest = "req"
Transfer = "xfr"
)
var prefixes = map[string]bool{
Project: true, Task: true, Session: true, Snapshot: true, Review: true,
InboxItem: true, InboxResponse: true, Blob: true, LeadNote: true,
WorkflowDefinition: true, WorkflowRun: true, Send: true,
Client: true, ClientRequest: true, Transfer: true,
}
func New(prefix string) string {
check(prefix)
out := make([]byte, randomLength)
buf := make([]byte, 1)
for i := 0; i < len(out); {
rand.Read(buf)
if int(buf[0]) >= 256/len(alphabet)*len(alphabet) {
continue
}
out[i] = alphabet[int(buf[0])%len(alphabet)]
i++
}
return prefix + string(out)
}
func Derive(prefix string, parts ...string) string {
check(prefix)
sum := sha256.Sum256([]byte(strings.Join(parts, "\x00")))
n := binary.BigEndian.Uint64(sum[:8])
out := make([]byte, randomLength)
for i := range out {
out[i] = alphabet[n%uint64(len(alphabet))]
n /= uint64(len(alphabet))
}
return prefix + string(out)
}
func check(prefix string) {
if !prefixes[prefix] {
panic(fmt.Sprintf("no id prefix %q", prefix))
}
}