// 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 }