package dbx import ( "encoding/hex" "fmt" "github.com/segmentio/ksuid" ) // ParseStringKSUIDAny parses a StringKSUID from a string, byte slice, ksuid.KSUID, // or nil. Accepts base62 string (27 bytes), raw binary (20 bytes), or hex-encoded // forms (40 or 54 bytes). func ParseStringKSUIDAny(src any) (StringKSUID, error) { id, err := parseKSUIDAny(src) if err != nil { return NilStringKSUID, err } return StringKSUID{KSUID: id}, nil } // ParseBinaryKSUIDAny parses a BinaryKSUID from the same accepted forms as // [ParseStringKSUIDAny]. func ParseBinaryKSUIDAny(src any) (BinaryKSUID, error) { id, err := parseKSUIDAny(src) if err != nil { return NilBinaryKSUID, err } return BinaryKSUID{KSUID: id}, nil } func parseKSUIDAny(src any) (ksuid.KSUID, error) { switch v := src.(type) { case ksuid.KSUID: return v, nil case StringKSUID: return v.KSUID, nil case BinaryKSUID: return v.KSUID, nil case string: return parseKSUIDBytes([]byte(v)) case []byte: return parseKSUIDBytes(v) case nil: return ksuid.Nil, nil default: return ksuid.Nil, fmt.Errorf("cannot parse KSUID from type %T", src) } } func parseKSUIDBytes(src []byte) (ksuid.KSUID, error) { if len(src) == 40 || len(src) == 54 { decoded := make([]byte, hex.DecodedLen(len(src))) if _, err := hex.Decode(decoded, src); err != nil { return ksuid.Nil, err } src = decoded } switch len(src) { case 0: return ksuid.Nil, nil case ksuidBinaryLength: return ksuid.FromBytes(src) case ksuidStringLength: return ksuid.Parse(string(src)) default: return ksuid.Nil, fmt.Errorf("cannot parse KSUID from byte slice of length %d", len(src)) } }