better heroscript encoding and support for ourtime

This commit is contained in:
timurgordon
2025-02-07 16:38:34 +03:00
parent c93fe755fd
commit 2aafab50ad
5 changed files with 74 additions and 43 deletions

View File

@@ -28,59 +28,28 @@ pub fn encode[T](val T) !string {
$if T is $struct { $if T is $struct {
e.encode_struct[T](val)! e.encode_struct[T](val)!
} $else $if T is $array { } $else $if T is $array {
e.add_child_list[T](val, 'TODO') e.encode_array(val)
} $else { } $else {
return error('can only add elements for struct or array of structs. \n${val}') return error('can only add elements for struct or array of structs. \n${val}')
} }
return e.export()! return e.export()
} }
// export exports an encoder into encoded heroscript // export exports an encoder into encoded heroscript
pub fn (e Encoder) export() !string { pub fn (e Encoder) export() string {
mut script := e.params.export( mut script := e.params.export(
pre: '!!define.${e.action_names.join('.')}' pre: '!!define.${e.action_names.join('.')}'
indent: ' ' indent: ' '
skip_empty: true skip_empty: true
) )
script += e.children.map(it.export()!).join('\n') script += e.children.map(it.export()).filter(it.trim_space() != '').join_lines().trim_space()
if script == '!!define.${e.action_names.join('.')}' {
return ''
}
return script return script
} }
// needs to be a struct we are adding
// parent is the name of the action e.g define.customer:contact
pub fn (mut e Encoder) add_child[T](val T, parent string) ! {
$if T is $array {
mut counter := 0
for valitem in val {
mut e2 := e.add_child[T](valitem, '${parent}:${counter}')!
}
return
}
mut e2 := Encoder{
params: paramsparser.Params{}
parent: &e
action_names: e.action_names.clone() // careful, if not cloned gets mutated later
}
$if T is $struct {
e2.params.set('key', parent)
e2.encode_struct[T](val)!
e.children << e2
} $else {
return error('can only add elements for struct or array of structs. \n${val}')
}
}
pub fn (mut e Encoder) add_child_list[U](val []U, parent string) ! {
for i in 0 .. val.len {
mut counter := 0
$if U is $struct {
e.add_child(val[i], '${parent}:${counter}')!
counter += 1
}
}
}
// needs to be a struct we are adding // needs to be a struct we are adding
// parent is the name of the action e.g define.customer:contact // parent is the name of the action e.g define.customer:contact
pub fn (mut e Encoder) add[T](val T) ! { pub fn (mut e Encoder) add[T](val T) ! {

View File

@@ -1,6 +1,7 @@
module encoderhero module encoderhero
import freeflowuniverse.herolib.data.paramsparser import freeflowuniverse.herolib.data.paramsparser
import freeflowuniverse.herolib.data.ourtime
import time import time
import v.reflection import v.reflection
@@ -13,6 +14,40 @@ struct Remark {
text string text string
} }
struct Company {
name string
founded ourtime.OurTime
employees []Person
}
const company = Company{
name: "Tech Corp"
founded: ourtime.new('2022-12-05 20:14')!
employees: [
person,
Person{
id: 2
name: "Alice"
age: 30
birthday: time.new(
day: 20
month: 6
year: 1990
)
car: Car{
name: "Alice's car"
year: 2018
}
profiles: [
Profile{
platform: 'LinkedIn'
url: 'linkedin.com/alice'
},
]
},
]
}
struct Person { struct Person {
Base Base
mut: mut:
@@ -43,7 +78,7 @@ struct Profile {
const person_heroscript = " const person_heroscript = "
!!define.person id:1 name:Bob birthday:'2012-12-12 00:00:00' !!define.person id:1 name:Bob birthday:'2012-12-12 00:00:00'
!!define.person.car name:'Bob\\'s car' year:2014 !!define.person.car name:'Bob\\'s car' year:2014
!!define.person.car.insurance expiration:'0000-00-00 00:00:00' provider:'' !!define.person.car.insurance provider:insurer
!!define.person.profile platform:Github url:github.com/example !!define.person.profile platform:Github url:github.com/example
" "
@@ -60,6 +95,9 @@ const person = Person{
car: Car{ car: Car{
name: "Bob's car" name: "Bob's car"
year: 2014 year: 2014
insurance: Insurance {
provider: "insurer"
}
} }
profiles: [ profiles: [
Profile{ Profile{
@@ -69,7 +107,23 @@ const person = Person{
] ]
} }
const company_script = "
!!define.company name:'Tech Corp' founded:'2022-12-05 20:14'
!!define.company.person id:1 name:Bob birthday:'2012-12-12 00:00:00'
!!define.company.person.car name:'Bob\'s car' year:2014
!!define.company.person.car.insurance provider:insurer'
!!define.company.person.profile platform:Github url:github.com/example
!!define.company.person id:2 name:Alice birthday:'1990-06-20 00:00:00'
!!define.company.person.car name:'Alice\'s car' year:2018
!!define.company.person.car.insurance
!!define.company.person.profile platform:LinkedIn url:linkedin.com/alice
"
fn test_encode() ! { fn test_encode() ! {
person_script := encode[Person](person)! person_script := encode[Person](person)!
assert person_script.trim_space() == person_heroscript.trim_space() assert person_script.trim_space() == person_heroscript.trim_space()
} assert encode[Company](company)!.trim_space() == company_script.trim_space()
}

View File

@@ -192,7 +192,7 @@ fn (p Params) export_helper(args_ ExportArgs) ![]ParamExportItem {
} }
fn val_is_empty(val string) bool { fn val_is_empty(val string) bool {
return val == '' || val == '[]' return val == '' || val == '[]' || val == '0000-00-00 00:00:00'
} }
@[params] @[params]

View File

@@ -290,4 +290,4 @@ fn test_export_text() {
} }
paramsout := params.export() paramsout := params.export()
assert paramsout.trim_space() == "text:'This content contains the character \\' in it'" assert paramsout.trim_space() == "text:'This content contains the character \\' in it'"
} }

View File

@@ -1,6 +1,7 @@
module paramsparser module paramsparser
import time import time
import freeflowuniverse.herolib.data.ourtime
import v.reflection import v.reflection
// import freeflowuniverse.herolib.data.encoderhero // import freeflowuniverse.herolib.data.encoderhero
// TODO: support more field types // TODO: support more field types
@@ -65,6 +66,13 @@ pub fn (params Params) decode_value[T](_ T, key string) !T {
return time.Time{} return time.Time{}
} }
return time.parse(time_str)! return time.parse(time_str)!
} $else $if T is ourtime.OurTime {
time_str := params.get(key)!
// todo: 'handle other null times'
if time_str == '0000-00-00 00:00:00' {
return ourtime.new('0000-00-00 00:00:00')!
}
return ourtime.new(time_str)!
} $else $if T is $struct { } $else $if T is $struct {
child_params := params.get_params(key)! child_params := params.get_params(key)!
child := child_params.decode_struct(T{})! child := child_params.decode_struct(T{})!
@@ -99,7 +107,7 @@ pub fn encode[T](t T, args EncodeArgs) !Params {
key = field_attrs['alias'] key = field_attrs['alias']
} }
$if val is string || val is int || val is bool || val is i64 || val is u32 $if val is string || val is int || val is bool || val is i64 || val is u32
|| val is time.Time { || val is time.Time || val is ourtime.OurTime {
params.set(key, '${val}') params.set(key, '${val}')
} $else $if field.is_enum { } $else $if field.is_enum {
params.set(key, '${int(val)}') params.set(key, '${int(val)}')