Documentation
¶
Overview ¶
The cgo backend — HyperUuid's measured lesson applied from day one: purego's per-call trampoline allocations would eat scalar parsing alive (its batch API was 19.6x faster than per-call precisely because of that overhead), so scalar-per-call HyperCast runs on real C calls wherever cgo is available. backend_purego.go is the fallback half of the pair — Windows, CGO_ENABLED=0, and cross-compiles land there automatically.
cgo can't call an opaquely-typed void* function pointer directly — it needs a real, statically-typed C call site — hence the three per-signature shims below, one per ABI shape (plain, numeric, unix).
Package hypercast provides allocation-lean scalar casts — booleans, numerics, UUIDs, temporals — calling directly into the native libhypercast shared library. Every door returns Go's own union idiom: (value, *Fault), where a nil fault is the success case and a non-nil one carries the closed reason plus the offending byte span. Never an error for bad data in the exception sense — *Fault implements error for composition, but the doors never panic on input; a panic here means a caller bug (a malformed NumFormat), never data.
Door names mirror the native ABI (I32, F64, Timestamp, ...) so the polyglot surface reads identically across bindings. Doors are generic over string | []byte — both cross zero-copy (the core only reads).
Go-flavored fidelity, stated honestly both ways: time.Time carries full nanoseconds across the whole 0001–9999 window, and time-of-day comes back as a time.Duration since midnight, also nanosecond-exact. But time.Duration's int64-nanosecond ceiling (±292 years) sits far below the core's ±10,000-year duration window, so the duration door returns the protobuf pair (Duration{Seconds, Nanos}) with a checked AsDuration() converter rather than silently wrapping.
Index ¶
- Variables
- func DateOnly[T Text](text T) (Date, *Fault)
- func DateOnlyOrdered[T Text](text T, order DateOrder) (Date, *Fault)
- func DateTime[T Text](text T, order DateOrder) (CivilDateTime, *Fault)
- func Span[T Text](text T) (Duration, *Fault)
- type CastFailure
- type CivilDateTime
- type Date
- type DateOrder
- type Duration
- type ExcelEpoch
- type Fault
- func Bool[T Text](text T) (bool, *Fault)
- func ExcelSerial[T Text](text T, epoch ExcelEpoch) (time.Time, *Fault)
- func F32[T Text](text T, format NumFormat) (float32, *Fault)
- func F64[T Text](text T, format NumFormat) (float64, *Fault)
- func I8[T Text](text T, format NumFormat) (int8, *Fault)
- func I16[T Text](text T, format NumFormat) (int16, *Fault)
- func I32[T Text](text T, format NumFormat) (int32, *Fault)
- func I64[T Text](text T, format NumFormat) (int64, *Fault)
- func TimeOfDay[T Text](text T) (time.Duration, *Fault)
- func Timestamp[T Text](text T) (time.Time, *Fault)
- func U8[T Text](text T, format NumFormat) (uint8, *Fault)
- func U16[T Text](text T, format NumFormat) (uint16, *Fault)
- func U32[T Text](text T, format NumFormat) (uint32, *Fault)
- func U64[T Text](text T, format NumFormat) (uint64, *Fault)
- func Unix[T Text](text T, precision UnixPrecision) (time.Time, *Fault)
- func Uuid[T Text](text T) (uuid.UUID, *Fault)
- type NumFormat
- type NumStyles
- type Text
- type UnixPrecision
Constants ¶
This section is empty.
Variables ¶
var Detect = NumFormat{DecimalSep: '.', GroupSep: ',', Styles: AllStyles | SeparatorDetect}
Detect is the detection profile — every lenience on, './,' roles resolved per input by SeparatorDetect's structural rules.
var Invariant = NumFormat{DecimalSep: '.', GroupSep: ',', Styles: AllStyles}
Invariant is the invariant profile — '.' decimal, ',' grouping, every lenience on.
Functions ¶
func DateOnlyOrdered ¶
DateOnlyOrdered casts a separated calendar date — three digit fields joined by one consistent separator (/, -, or .) — under the caller-declared DateOrder. The year field is four digits wherever the order puts it (two-digit years mean century guessing, which never happens here); an undefined order is a caller bug and panics, never a verdict. The strict DateOnly door keeps rejecting every separated form.
func DateTime ¶
func DateTime[T Text](text T, order DateOrder) (CivilDateTime, *Fault)
DateTime casts a zone-less civil date-time — the shape untrusted feeds actually send ("1/7/2026 3:04 PM", "2026-01-07 15:04:05") — under the caller-declared DateOrder. The date part follows DateOnlyOrdered's grammar; the optional time part (one space or 'T' after the date) is 24-hour h:mm[:ss[.f]] or 12-hour with an AM/PM marker; absent, the time is midnight. No zone is read and none is invented — Timestamp stays the strict RFC 3339 instant door. An undefined order is a caller bug and panics, never a verdict.
Types ¶
type CastFailure ¶
type CastFailure int32
CastFailure is the closed set of reasons a cast can fail — the native core's verdict codes, verbatim.
const ( // Empty means required input was empty or whitespace. Empty CastFailure = 1 // Malformed means input was present but not recognizable as the target type. Malformed CastFailure = 2 // OutOfRange means well-formed but outside the target's range — "256" for a U8, // 1e400 for an F64. OutOfRange CastFailure = 3 )
func (CastFailure) String ¶
func (f CastFailure) String() string
type CivilDateTime ¶
CivilDateTime is a wall-clock date and time with no zone — exactly what zone-less text like "1/7/2026 3:04 PM" actually names. Deliberately not a time.Time: without a zone there is no instant, and inventing one (assuming UTC, say) would be a silent value error of up to ±14 hours. Fuse a zone yourself when you know it: time.Date(d.Date.Year, d.Date.Month, d.Date.Day, 0, 0, 0, 0, loc).Add(d.TimeOfDay).
type Date ¶
Date is a calendar date with no time or zone — the protobuf google.type.Date fields. Go has no standard date-only type; this keeps the core's digits exactly.
type DateOrder ¶
type DateOrder uint32
DateOrder is the caller-declared field order of a separated calendar date — no guessing, ever: "1/7/2026" is January 7th (MonthDayYear, the en-US order) or July 1st (DayMonthYear, the en-GB order) only because the caller said which.
type Duration ¶
Duration is the protobuf pair — whole seconds plus same-signed nanoseconds. Returned instead of time.Duration because the core's ±10,000-year window exceeds time.Duration's int64-nanosecond ceiling (±292 years); AsDuration converts when the value fits.
type ExcelEpoch ¶
type ExcelEpoch uint32
ExcelEpoch is the date system an Excel serial number is expressed in. Spreadsheets carry no marker for this — it is a workbook-level setting — so the caller states it, the same way UnixPrecision and DateOrder are declared rather than guessed.
const ( // Excel1900 is the Windows default: serial 1 is 1900-01-01, and serial 60 is a // February 29th that never existed. Excel1900 ExcelEpoch = 1 // Excel1904 is the legacy Macintosh system, still selectable today: serial 0 is // 1904-01-01, with no phantom day anywhere in it. Excel1904 ExcelEpoch = 2 )
The declared Excel date systems — the native core's codes, verbatim.
type Fault ¶
type Fault struct {
Reason CastFailure
Offset int
Length int
}
Fault is the failure case of a cast: a closed reason plus the offending span, as byte offsets into the input (identical to what the door received — string and []byte inputs are both raw UTF-8 here). Implements error so verdicts compose with Go's error plumbing, but nothing is captured or formatted until Error() is actually called.
func Bool ¶
Bool casts boolean text: true/false plus the conventions untrusted sources actually send (t/f, yes/no, y/n, 1/0, on/off, enabled/disabled, active/inactive, checked/unchecked, in/out), ASCII case-insensitive.
func ExcelSerial ¶
func ExcelSerial[T Text](text T, epoch ExcelEpoch) (time.Time, *Fault)
ExcelSerial casts an Excel date serial under a caller-declared ExcelEpoch to a UTC time.Time. The whole part counts days from the system's own day zero and the fraction is the time of day, so "45292.75" is 2024-01-01T18:00:00Z. A spreadsheet cell carries no zone and none is invented.
The 1900 system contains a day that never existed: serial 60 is 1900-02-29, kept deliberately because Lotus 1-2-3 wrongly treated 1900 as a leap year and Excel copied the bug for file compatibility. It is Malformed here — the same verdict DateOnly gives the text "1900-02-29" — so every serial above it is shifted one day against a naive count, which is the arithmetic hand-rolled conversions get wrong.
An undefined epoch is a caller bug and panics, never a verdict.
func F32 ¶
F32 casts real text under the declared format: finite values only (NaN/Infinity literals are Malformed, overflow to infinity is OutOfRange), declared separators and grouping, accounting parentheses, exponent, and trailing percent (50% is 0.5).
func I8 ¶
I8 casts integer text under the declared format: the type's own range, declared grouping, accounting parentheses, non-negative exponent (1e3 is 1000; a decimal point is never accepted), and 0x/&H/0b two's-complement radix prefixes (0xFF is -1). The other integer doors share these rules at their own widths.
func TimeOfDay ¶
TimeOfDay casts an ISO 24-hour time-of-day to a time.Duration since midnight — nanosecond-exact, and comfortably inside time.Duration's range.
func Timestamp ¶
Timestamp casts an RFC 3339 instant — zone mandatory — to a UTC time.Time at full nanosecond fidelity across the whole 0001–9999 window.
func Unix ¶
func Unix[T Text](text T, precision UnixPrecision) (time.Time, *Fault)
Unix casts an integer Unix-epoch value under a caller-declared unit to a UTC time.Time. An undefined precision is a caller bug and panics, never a verdict.
type NumFormat ¶
NumFormat is the caller-declared numeric notation for the integer and real doors. The core carries no culture data — a call site parsing culture-sensitive text declares its format out loud (Invariant, or a literal); there is no default, the same stance every binding in this repo takes. Equal separators are a caller bug and panic, never a verdict.
type NumStyles ¶
type NumStyles uint32
NumStyles are the lenience flags of NumFormat — bit-for-bit the native core's flags.
const ( // Grouping permits the group separator between digits (sizes not validated — between // digits is the rule). Grouping NumStyles = 1 << iota // Parentheses permits accounting negation: (1,234) is -1234. Parentheses // Exponent permits exponent notation. Integer doors reject a negative exponent. Exponent // RadixPrefixes permits 0x/&H/0b two's-complement prefixes (0xFF is -1 for an I8). RadixPrefixes // Percent permits a trailing %, dividing by 100. Real doors only. Percent // SeparatorDetect resolves the './,' roles per input from structure instead of the // declared separators (which are ignored while this flag is set). Detection, not // sniffing: a repeated separator is grouping (1.234.567,89); with both present the // rightmost is the decimal; a single separator with a non-3-digit right run is the // decimal (3,1415); with exactly 3 digits right, only a 0 integer part proves decimal // (0,785). Genuinely ambiguous input (12.185, 1,000) is Malformed at the separator, // never guessed. SeparatorDetect NumStyles = 1 << 5 // AllStyles is every lenience on. AllStyles = Grouping | Parentheses | Exponent | RadixPrefixes | Percent )
type UnixPrecision ¶
type UnixPrecision uint32
UnixPrecision is the declared unit of a Unix-epoch value — no magnitude guessing, ever.
const ( Seconds UnixPrecision = 1 Milliseconds UnixPrecision = 2 Microseconds UnixPrecision = 3 Nanoseconds UnixPrecision = 4 )
The declared units a Unix-epoch value can carry — the native core's codes, verbatim.