package model
import (
"encoding/base32"
"fmt"
"io"
"github.com/google/uuid"
)
// Crockford's low-ambiguity base32 alphabet
var base32Encoding = base32.
NewEncoding("0123456789ABCDEFGHJKMNPQRSTVWXYZ").
WithPadding(base32.NoPadding)
type ID struct {
uuid uuid.UUID
}
// Creates a new resource ID.
func NewID() ID {
uuid, err := uuid.NewV7()
if err != nil {
panic(err)
}
return ID{
uuid: uuid,
}
}
// Returns the UUID representation of this ID.
func (id *ID) UUID() uuid.UUID {
return id.uuid
}
// Returns the string representation of this ID.
func (id *ID) String() string {
return base32Encoding.EncodeToString(id.uuid[:])
}
func (id ID) MarshalGQL(w io.Writer) {
w.Write([]byte(fmt.Sprintf(`"%s"`, id.String())))
}
func (id *ID) UnmarshalGQL(v interface{}) error {
switch v := v.(type) {
case string:
bytes, err := base32Encoding.DecodeString(v)
if err != nil {
return err
}
id.uuid, err = uuid.FromBytes(bytes)
if err != nil {
return err
}
return nil
default:
return fmt.Errorf("%T is not a valid ID", v)
}
}
// database/sql.Scanner
func (id *ID) Scan(src any) error {
var uuid uuid.UUID
err := uuid.Scan(src)
if err != nil {
return err
}
id.uuid = uuid
return nil
}