data.encoderhero #
HeroEncoder - Simple Struct Serialization
HeroEncoder provides bidirectional conversion between V structs and HeroScript format.
Design: Single Level Deep Only
This module is designed for simple, flat structs only:
✅ Supported:
- Basic types:
int
,string
,bool
,f32
,f64
,u8
,u16
,u32
,u64
,i8
,i16
,i32
,i64
- Arrays of basic types:
[]string
,[]int
, etc. - Time handling:
ourtime.OurTime
- Embedded structs (for inheritance)
❌ Not Supported:
- Nested structs (non-embedded fields)
- Arrays of structs
- Complex nested structures
Use ourdb
or json
for complex data structures.
HeroScript Format
!!define.typename param1:value1 param2:'value with spaces' list:item1,item2,item3
or
!!configure.typename param1:value1 param2:'value with spaces'
Basic Usage
Simple Struct
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import incubaid.herolib.data.encoderhero
import incubaid.herolib.data.ourtime
struct Person {
mut:
name string
age int = 20
active bool
birthday ourtime.OurTime
}
mut person := Person{
name: 'Bob'
age: 25
active: true
birthday: ourtime.new('2000-01-15')!
}
// Encode to heroscript
heroscript := encoderhero.encode[Person](person)!
println(heroscript)
// Output: !!define.person name:Bob age:25 active:true birthday:'2000-01-15 00:00'
// Decode back
person2 := encoderhero.decode[Person](heroscript)!
assert person2.name == person.name
assert person2.age == person.age
Embedded Structs (Inheritance)
import incubaid.herolib.data.encoderhero
import incubaid.herolib.data.ourtime
struct Base {
id int
created ourtime.OurTime
}
struct User {
Base // Embedded struct - fields are flattened
mut:
name string
email string
}
user := User{
id: 123
created: ourtime.now()
name: 'Alice'
email: 'alice@example.com'
}
heroscript := encoderhero.encode[User](user)!
// Output: !!define.user id:123 created:'2024-01-15 10:30' name:Alice email:alice@example.com
decoded := encoderhero.decode[User](heroscript)!
assert decoded.id == user.id
assert decoded.name == user.name
Arrays of Basic Types
struct Config {
mut:
hosts []string
ports []int
name string
}
config := Config{
name: 'prod'
hosts: ['server1.com', 'server2.com', 'server3.com']
ports: [8080, 8081, 8082]
}
heroscript := encoderhero.encode[Config](config)!
// Output: !!define.config name:prod hosts:server1.com,server2.com,server3.com ports:8080,8081,8082
decoded := encoderhero.decode[Config](heroscript)!
assert decoded.hosts.len == 3
assert decoded.ports[0] == 8080
Skip Attributes
Use @[skip]
to exclude fields from encoding/decoding:
struct MyStruct {
id int
name string
runtime_cache ?&Cache @[skip] // Won't be encoded/decoded
}
Common Use Cases
Configuration Files
struct PostgresqlClient {
pub mut:
name string = 'default'
user string = 'root'
port int = 5432
host string = 'localhost'
password string
dbname string = 'postgres'
}
// Load from heroscript
script := '!!postgresql_client.configure name:production user:app_user port:5433'
client := encoderhero.decode[PostgresqlClient](script)!
Data Exchange
struct ApiResponse {
mut:
status int
message string
timestamp ourtime.OurTime
errors []string
}
response := ApiResponse{
status: 200
message: 'Success'
timestamp: ourtime.now()
errors: []
}
// Send as heroscript
script := encoderhero.encode[ApiResponse](response)!
Time Handling with OurTime
Always use incubaid.herolib.data.ourtime.OurTime
for time fields:
import incubaid.herolib.data.ourtime
struct Event {
mut:
name string
start_time ourtime.OurTime
end_time ourtime.OurTime
}
event := Event{
name: 'Meeting'
start_time: ourtime.new('2024-06-15 14:00')!
end_time: ourtime.new('2024-06-15 15:30')!
}
script := encoderhero.encode[Event](event)!
decoded := encoderhero.decode[Event](script)!
// OurTime provides flexible formatting
println(decoded.start_time.str()) // '2024-06-15 14:00'
println(decoded.start_time.day()) // '2024-06-15'
Error Handling
// Decoding with error handling
decoded := encoderhero.decode[MyStruct](heroscript) or {
eprintln('Failed to decode: ${err}')
MyStruct{} // Return default
}
// Encoding should not fail for simple structs
encoded := encoderhero.encode[MyStruct](my_struct)!
Limitations
For Complex Data Structures, Use:
incubaid.herolib.data.ourdb
- For nested data storage- V's built-in
json
module - For JSON serialization - Custom serialization - For specific needs
This module is optimized for:
- Configuration files
- Simple data exchange
- Flat data structures
- Heroscript integration
fn decode #
fn decode[T](data string) !T
fn encode #
fn encode[T](val T) !string
encode is a generic function that encodes a type into a HEROSCRIPT string.
interface Encodable #
interface Encodable {
heroscript() string
}
Encodable is an interface for custom heroscript encoding
struct Decoder #
struct Decoder[T] {
pub mut:
object T
data string
}
struct Encoder #
struct Encoder {
pub mut:
escape_unicode bool = true
action_name string
action_names []string
params paramsparser.Params
}
Encoder encodes a struct into HEROSCRIPT representation.
fn (Encoder) export #
fn (e Encoder) export() !string
export exports an encoder into encoded heroscript
fn (Encoder) encode_struct #
fn (mut e Encoder) encode_struct[T](t T) !
encode the struct - single level only