mirror of
https://github.com/luxfi/zap.git
synced 2026-07-26 22:53:31 +00:00
209 lines
4.8 KiB
Go
209 lines
4.8 KiB
Go
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package zap
|
|
|
|
// Schema types for ZAP messages.
|
|
// These can be used to generate code or for runtime reflection.
|
|
|
|
// Type represents a ZAP type.
|
|
type Type uint8
|
|
|
|
const (
|
|
TypeVoid Type = iota
|
|
TypeBool
|
|
TypeInt8
|
|
TypeInt16
|
|
TypeInt32
|
|
TypeInt64
|
|
TypeUint8
|
|
TypeUint16
|
|
TypeUint32
|
|
TypeUint64
|
|
TypeFloat32
|
|
TypeFloat64
|
|
TypeText
|
|
TypeBytes
|
|
TypeList
|
|
TypeStruct
|
|
TypeEnum
|
|
TypeUnion
|
|
)
|
|
|
|
// Field describes a struct field.
|
|
type Field struct {
|
|
Name string
|
|
Type Type
|
|
Offset int // Byte offset within struct
|
|
ListElem Type // Element type if Type == TypeList
|
|
StructName string // Struct name if Type == TypeStruct
|
|
Default any // Default value
|
|
}
|
|
|
|
// Struct describes a ZAP struct.
|
|
type Struct struct {
|
|
Name string
|
|
Size int // Total size in bytes
|
|
Fields []Field
|
|
}
|
|
|
|
// Enum describes a ZAP enum.
|
|
type Enum struct {
|
|
Name string
|
|
Type Type // Underlying type (Uint8, Uint16, etc.)
|
|
Values map[string]uint64
|
|
}
|
|
|
|
// Schema describes a complete ZAP schema.
|
|
type Schema struct {
|
|
Name string
|
|
Structs map[string]*Struct
|
|
Enums map[string]*Enum
|
|
}
|
|
|
|
// NewSchema creates a new empty schema.
|
|
func NewSchema(name string) *Schema {
|
|
return &Schema{
|
|
Name: name,
|
|
Structs: make(map[string]*Struct),
|
|
Enums: make(map[string]*Enum),
|
|
}
|
|
}
|
|
|
|
// AddStruct adds a struct to the schema.
|
|
func (s *Schema) AddStruct(st *Struct) {
|
|
s.Structs[st.Name] = st
|
|
}
|
|
|
|
// AddEnum adds an enum to the schema.
|
|
func (s *Schema) AddEnum(e *Enum) {
|
|
s.Enums[e.Name] = e
|
|
}
|
|
|
|
// TypeSize returns the size of a type in bytes.
|
|
func TypeSize(t Type) int {
|
|
switch t {
|
|
case TypeBool, TypeInt8, TypeUint8:
|
|
return 1
|
|
case TypeInt16, TypeUint16:
|
|
return 2
|
|
case TypeInt32, TypeUint32, TypeFloat32:
|
|
return 4
|
|
case TypeInt64, TypeUint64, TypeFloat64:
|
|
return 8
|
|
case TypeText, TypeBytes:
|
|
return 8 // offset (4) + length (4)
|
|
case TypeList:
|
|
return 8 // offset (4) + length (4)
|
|
case TypeStruct:
|
|
return 4 // offset (4)
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// Example schema definition helpers
|
|
|
|
// StructBuilder helps build struct definitions.
|
|
type StructBuilder struct {
|
|
s *Struct
|
|
offset int
|
|
}
|
|
|
|
// NewStructBuilder creates a struct builder.
|
|
func NewStructBuilder(name string) *StructBuilder {
|
|
return &StructBuilder{
|
|
s: &Struct{Name: name},
|
|
}
|
|
}
|
|
|
|
// Bool adds a bool field.
|
|
func (sb *StructBuilder) Bool(name string) *StructBuilder {
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeBool, Offset: sb.offset})
|
|
sb.offset += 1
|
|
return sb
|
|
}
|
|
|
|
// Int32 adds an int32 field.
|
|
func (sb *StructBuilder) Int32(name string) *StructBuilder {
|
|
sb.align(4)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeInt32, Offset: sb.offset})
|
|
sb.offset += 4
|
|
return sb
|
|
}
|
|
|
|
// Int64 adds an int64 field.
|
|
func (sb *StructBuilder) Int64(name string) *StructBuilder {
|
|
sb.align(8)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeInt64, Offset: sb.offset})
|
|
sb.offset += 8
|
|
return sb
|
|
}
|
|
|
|
// Uint32 adds a uint32 field.
|
|
func (sb *StructBuilder) Uint32(name string) *StructBuilder {
|
|
sb.align(4)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeUint32, Offset: sb.offset})
|
|
sb.offset += 4
|
|
return sb
|
|
}
|
|
|
|
// Uint64 adds a uint64 field.
|
|
func (sb *StructBuilder) Uint64(name string) *StructBuilder {
|
|
sb.align(8)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeUint64, Offset: sb.offset})
|
|
sb.offset += 8
|
|
return sb
|
|
}
|
|
|
|
// Float64 adds a float64 field.
|
|
func (sb *StructBuilder) Float64(name string) *StructBuilder {
|
|
sb.align(8)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeFloat64, Offset: sb.offset})
|
|
sb.offset += 8
|
|
return sb
|
|
}
|
|
|
|
// Text adds a text field.
|
|
func (sb *StructBuilder) Text(name string) *StructBuilder {
|
|
sb.align(4)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeText, Offset: sb.offset})
|
|
sb.offset += 8 // offset + length
|
|
return sb
|
|
}
|
|
|
|
// Bytes adds a bytes field.
|
|
func (sb *StructBuilder) Bytes(name string) *StructBuilder {
|
|
sb.align(4)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeBytes, Offset: sb.offset})
|
|
sb.offset += 8
|
|
return sb
|
|
}
|
|
|
|
// List adds a list field.
|
|
func (sb *StructBuilder) List(name string, elemType Type) *StructBuilder {
|
|
sb.align(4)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeList, Offset: sb.offset, ListElem: elemType})
|
|
sb.offset += 8
|
|
return sb
|
|
}
|
|
|
|
// Struct adds a nested struct field.
|
|
func (sb *StructBuilder) Struct(name string, structName string) *StructBuilder {
|
|
sb.align(4)
|
|
sb.s.Fields = append(sb.s.Fields, Field{Name: name, Type: TypeStruct, Offset: sb.offset, StructName: structName})
|
|
sb.offset += 4
|
|
return sb
|
|
}
|
|
|
|
// Build finalizes and returns the struct.
|
|
func (sb *StructBuilder) Build() *Struct {
|
|
sb.align(8) // Final alignment
|
|
sb.s.Size = sb.offset
|
|
return sb.s
|
|
}
|
|
|
|
func (sb *StructBuilder) align(n int) {
|
|
sb.offset = (sb.offset + n - 1) &^ (n - 1)
|
|
}
|