Files
orbit/model/id.go

66 lines
1.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package model 提供 Orbit 各模块共用且不绑定存储实现的基础类型。
// 服务端模型不直接作为公开 SDK 协议。
package model
import (
"crypto/rand"
"database/sql/driver"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
)
// ID 是 128 位随机标识,对外使用小写十六进制,MySQL 使用 BINARY(16)。
// 标识只用于定位资源,不能作为访问凭据。
type ID string
func NewID() (ID, error) {
var b [16]byte
if _, err := rand.Read(b[:]); err != nil {
return "", err
}
return ID(hex.EncodeToString(b[:])), nil
}
func (id ID) Validate() error {
if len(id) != 32 {
return errors.New("id must contain 32 lowercase hexadecimal characters")
}
for _, c := range id {
if !(c >= '0' && c <= '9' || c >= 'a' && c <= 'f') {
return errors.New("id must contain lowercase hexadecimal characters")
}
}
return nil
}
func (id ID) Value() (driver.Value, error) {
if err := id.Validate(); err != nil {
return nil, err
}
return hex.DecodeString(string(id))
}
func (id *ID) Scan(src any) error {
b, ok := src.([]byte)
if !ok || len(b) != 16 {
return fmt.Errorf("id: expected BINARY(16), got %T", src)
}
*id = ID(hex.EncodeToString(b))
return nil
}
func (id *ID) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
candidate := ID(s)
if err := candidate.Validate(); err != nil {
return err
}
*id = candidate
return nil
}