API Reference
Complete API documentation for the atom package.
Package
import "github.com/zoobz-io/atom"
Functions
Use
func Use[T any]() (*Atomizer[T], error)
Registers and returns an Atomizer for type T.
- First call builds the atomizer via reflection
- Subsequent calls return the cached instance
- Returns error if T contains unsupported field types
Example:
atomizer, err := atom.Use[User]()
if err != nil {
log.Fatalf("registration failed: %v", err)
}
Errors:
"type X: field Y: unsupported type Z"- Field type not supported"type X: field Y: only string map keys are supported"- Non-string map keys not allowed
AllTables
func AllTables() []Table
Returns all table types in canonical order.
Example:
for _, t := range atom.AllTables() {
fmt.Println(t)
}
TableForField
func TableForField(spec Spec, field string) (Table, bool)
Returns the storage table for a field by Spec lookup.
- Enables field→table lookup without the generic type parameter
- Returns
"", falseif the type was not registered viaUse[T]() - Returns
"", falseif the field does not exist
Example:
atomizer, _ := atom.Use[User]()
spec := atomizer.Spec()
// Later, without knowing T:
table, ok := atom.TableForField(spec, "Age")
if ok {
fmt.Println(table) // "ints"
}
FieldsFor
func FieldsFor(spec Spec) ([]Field, bool)
Returns all field-to-table mappings for a registered type.
- Returns
nil, falseif the type was not registered viaUse[T]() - Nested struct fields are excluded (they have no table)
Example:
atomizer, _ := atom.Use[User]()
fields, ok := atom.FieldsFor(atomizer.Spec())
if ok {
for _, f := range fields {
fmt.Printf("%s -> %s\n", f.Name, f.Table)
}
}
Types
AtomizerT
type Atomizer[T any] struct {
// contains filtered or unexported fields
}
Provides typed bidirectional conversion for type T.
Methods
Atomize
func (a *Atomizer[T]) Atomize(obj *T) *Atom
Converts a struct to its atomic representation.
- If T implements
Atomizable, that method is used - Otherwise, reflection is used
Example:
user := &User{Name: "Alice", Age: 30}
atom := atomizer.Atomize(user)
Deatomize
func (a *Atomizer[T]) Deatomize(atom *Atom) (*T, error)
Reconstructs a struct from an Atom.
- If T implements
Deatomizable, that method is used - Otherwise, reflection is used
- Returns error on overflow or validation failure
Example:
user, err := atomizer.Deatomize(atom)
if err != nil {
log.Printf("deatomize failed: %v", err)
}
NewAtom
func (a *Atomizer[T]) NewAtom() *Atom
Creates an Atom with pre-allocated maps for this type.
Only allocates maps that will be used based on T's fields.
Example:
atom := atomizer.NewAtom()
atom.Strings["Name"] = "Bob"
Spec
func (a *Atomizer[T]) Spec() Spec
Returns the type specification for T.
Example:
spec := atomizer.Spec()
fmt.Println(spec.TypeName) // "User"
fmt.Println(spec.PackageName) // "github.com/example/app"
Fields
func (a *Atomizer[T]) Fields() []Field
Returns all fields with their table mappings.
Example:
for _, f := range atomizer.Fields() {
fmt.Printf("%s -> %s\n", f.Name, f.Table)
}
// ID -> ints
// Name -> strings
FieldsIn
func (a *Atomizer[T]) FieldsIn(table Table) []string
Returns field names stored in the given table.
Example:
stringFields := atomizer.FieldsIn(atom.TableStrings)
// ["Name", "Email"]
TableFor
func (a *Atomizer[T]) TableFor(field string) (Table, bool)
Returns the table for a field name.
Example:
table, ok := atomizer.TableFor("Age")
if ok {
fmt.Println(table) // "ints"
}
Atom
type Atom struct {
// Scalars
Strings map[string]string
Ints map[string]int64
Uints map[string]uint64
Floats map[string]float64
Bools map[string]bool
Times map[string]time.Time
Bytes map[string][]byte
// Pointers (nullable)
StringPtrs map[string]*string
IntPtrs map[string]*int64
UintPtrs map[string]*uint64
FloatPtrs map[string]*float64
BoolPtrs map[string]*bool
TimePtrs map[string]*time.Time
BytePtrs map[string]*[]byte
// Slices
StringSlices map[string][]string
IntSlices map[string][]int64
UintSlices map[string][]uint64
FloatSlices map[string][]float64
BoolSlices map[string][]bool
TimeSlices map[string][]time.Time
ByteSlices map[string][][]byte
// Maps (string-keyed)
StringMaps map[string]map[string]string
IntMaps map[string]map[string]int64
UintMaps map[string]map[string]uint64
FloatMaps map[string]map[string]float64
BoolMaps map[string]map[string]bool
TimeMaps map[string]map[string]time.Time
ByteMaps map[string]map[string][]byte
// Nested
Nested map[string]Atom
NestedSlices map[string][]Atom
NestedMaps map[string]map[string]Atom
// Metadata
Spec Spec
}
Holds decomposed atomic values by type.
Methods
Clone
func (a *Atom) Clone() *Atom
Returns a deep copy of the Atom.
- All maps are copied (not shared)
- Pointer values are dereferenced and copied
- Nested atoms are recursively cloned
- Nil entries in pointer maps are preserved
- Returns nil if called on nil
Example:
original := atomizer.Atomize(user)
copy := original.Clone()
// Modify copy without affecting original
copy.Strings["Name"] = "Modified"
fmt.Println(original.Strings["Name"]) // Unchanged
Table
type Table string
Identifies the segregated storage table for atomic values.
Constants
const (
TableStrings Table = "strings"
TableInts Table = "ints"
TableUints Table = "uints"
TableFloats Table = "floats"
TableBools Table = "bools"
TableTimes Table = "times"
TableBytes Table = "bytes"
TableBytePtrs Table = "byte_ptrs"
TableStringPtrs Table = "string_ptrs"
TableIntPtrs Table = "int_ptrs"
TableUintPtrs Table = "uint_ptrs"
TableFloatPtrs Table = "float_ptrs"
TableBoolPtrs Table = "bool_ptrs"
TableTimePtrs Table = "time_ptrs"
TableStringSlices Table = "string_slices"
TableIntSlices Table = "int_slices"
TableUintSlices Table = "uint_slices"
TableFloatSlices Table = "float_slices"
TableBoolSlices Table = "bool_slices"
TableTimeSlices Table = "time_slices"
TableByteSlices Table = "byte_slices"
)
Methods
Prefix
func (t Table) Prefix() string
Returns the storage key prefix for this table.
Example:
prefix := atom.TableStrings.Prefix()
// "strings:"
Spec
type Spec = sentinel.Metadata
Type metadata describing a struct type. Aliased from sentinel.Metadata:
type Metadata struct {
TypeName string // e.g., "User"
PackageName string // e.g., "github.com/example/app"
Fields []FieldMetadata // All exported fields
Relationships []TypeRelationship // References to other types
}
Most commonly used fields:
TypeName- The short type namePackageName- The full package path
Field
type Field struct {
Name string
Table Table
}
Maps a field name to its storage table.
Interfaces
Atomizable
type Atomizable interface {
Atomize(*Atom)
}
Allows types to provide custom atomization logic.
If implemented, Atomizer.Atomize() calls this method instead of using reflection.
Example:
func (u *User) Atomize(a *Atom) {
a.Strings["Name"] = u.Name
a.Ints["Age"] = u.Age
}
Deatomizable
type Deatomizable interface {
Deatomize(*Atom) error
}
Allows types to provide custom deatomization logic.
If implemented, Atomizer.Deatomize() calls this method instead of using reflection.
Example:
func (u *User) Deatomize(a *Atom) error {
u.Name = a.Strings["Name"]
u.Age = a.Ints["Age"]
return nil
}
Errors
Sentinel errors for programmatic error handling via errors.Is().
ErrOverflow
var ErrOverflow = errors.New("numeric overflow")
Returned during Deatomize() when an int64/uint64/float64 value cannot fit in a narrower type (e.g., int8, uint16, float32).
Example:
_, err := atomizer.Deatomize(atom)
if errors.Is(err, atom.ErrOverflow) {
// Handle overflow
}
ErrUnsupportedType
var ErrUnsupportedType = errors.New("unsupported type")
Returned during Use[T]() for types like channels, functions, interfaces, or maps with non-string keys.
Example:
_, err := atom.Use[BadType]()
if errors.Is(err, atom.ErrUnsupportedType) {
// Handle unsupported type
}
ErrSizeMismatch
var ErrSizeMismatch = errors.New("size mismatch")
Returned during Deatomize() when a []byte value is assigned to a [N]byte field but the lengths differ.
Example:
_, err := atomizer.Deatomize(atom)
if errors.Is(err, atom.ErrSizeMismatch) {
// Handle size mismatch
}
Type Mappings
| Go Type | Table | Atom Field |
|---|---|---|
string | strings | Strings |
int, int8, int16, int32, int64 | ints | Ints |
uint, uint8, uint16, uint32, uint64 | uints | Uints |
float32, float64 | floats | Floats |
bool | bools | Bools |
time.Time | times | Times |
[]byte | bytes | Bytes |
*string | string_ptrs | StringPtrs |
*int64 | int_ptrs | IntPtrs |
*uint64 | uint_ptrs | UintPtrs |
*float64 | float_ptrs | FloatPtrs |
*bool | bool_ptrs | BoolPtrs |
*time.Time | time_ptrs | TimePtrs |
*[]byte | byte_ptrs | BytePtrs |
[]string | string_slices | StringSlices |
[]int64 | int_slices | IntSlices |
[]uint64 | uint_slices | UintSlices |
[]float64 | float_slices | FloatSlices |
[]bool | bool_slices | BoolSlices |
[]time.Time | time_slices | TimeSlices |
[][]byte | byte_slices | ByteSlices |
map[string]string | string_maps | StringMaps |
map[string]int64 | int_maps | IntMaps |
map[string]uint64 | uint_maps | UintMaps |
map[string]float64 | float_maps | FloatMaps |
map[string]bool | bool_maps | BoolMaps |
map[string]time.Time | time_maps | TimeMaps |
map[string][]byte | byte_maps | ByteMaps |
struct | - | Nested |
*struct | - | Nested |
[]struct | - | NestedSlices |
map[string]struct | nested_maps | NestedMaps |