Files

153 lines
4.2 KiB
Go

package module
import (
"errors"
"unsafe"
"aego/core/errs"
"aego/core/mathx"
"aego/format/aetext"
"aego/schema"
)
func codecFits(td *schema.TypeDescriptor) error {
for i := range td.Fields {
fd := &td.Fields[i]
if !fd.Flags.Has(schema.FlagSerialize) {
continue
}
switch fd.Kind {
case schema.KindBool, schema.KindInt32, schema.KindInt64, schema.KindFloat32, schema.KindFloat64,
schema.KindVec2, schema.KindColor, schema.KindString, schema.KindEnum:
default:
return errs.New(errs.EngineModule, "field "+td.FullName+"."+fd.Name+" of kind "+fd.Kind.String()+" needs a custom section codec")
}
}
return nil
}
func encodeFields(td *schema.TypeDescriptor, p unsafe.Pointer, n *aetext.Node) {
for i := range td.Fields {
fd := &td.Fields[i]
if !fd.Flags.Has(schema.FlagSerialize) {
continue
}
var v schema.Value
fd.Get(p, &v)
n.Fields = append(n.Fields, aetext.Field{Name: fd.Name, Value: toText(fd, v)})
}
}
func decodeFields(td *schema.TypeDescriptor, p unsafe.Pointer, n *aetext.Node) error {
if len(n.Blocks) > 0 {
return sectionErr(n.Head, "unknown block "+n.Blocks[0].Head)
}
for _, f := range n.Fields {
fd, ok := td.Field(f.Name)
if !ok || !fd.Flags.Has(schema.FlagSerialize) {
return sectionErr(n.Head, "unknown setting "+f.Name)
}
v, err := fromText(fd, f.Value)
if err != nil {
return sectionErr(n.Head, f.Name+": "+err.Error())
}
if err := fd.Set(p, v); err != nil {
return sectionErr(n.Head, f.Name+": "+err.Error())
}
}
return nil
}
func toText(fd *schema.FieldDescriptor, v schema.Value) aetext.Value {
switch fd.Kind {
case schema.KindBool:
return aetext.Bool(v.I != 0)
case schema.KindInt32, schema.KindInt64:
return aetext.Int(v.I)
case schema.KindFloat32:
return aetext.Float32(float32(v.F))
case schema.KindFloat64:
return aetext.Float64(v.F)
case schema.KindVec2:
return aetext.List(aetext.Float32(v.V.X), aetext.Float32(v.V.Y))
case schema.KindColor:
return aetext.List(aetext.Float32(v.C.R), aetext.Float32(v.C.G), aetext.Float32(v.C.B), aetext.Float32(v.C.A))
case schema.KindEnum:
if name, ok := fd.EnumNameOf(v.I); ok {
return aetext.Ident(name)
}
return aetext.Int(v.I)
}
return aetext.String(v.S)
}
func numbers(a aetext.Value, n int) ([]float32, error) {
if a.Kind != aetext.VList || len(a.List) != n {
return nil, errors.New("expected a list of numbers")
}
out := make([]float32, n)
for i, x := range a.List {
if x.Kind != aetext.VInt && x.Kind != aetext.VFloat {
return nil, errors.New("expected a list of numbers")
}
out[i] = float32(x.AsFloat())
}
return out, nil
}
func fromText(fd *schema.FieldDescriptor, a aetext.Value) (schema.Value, error) {
num := a.Kind == aetext.VInt || a.Kind == aetext.VFloat
switch fd.Kind {
case schema.KindBool:
if a.Kind != aetext.VBool {
return schema.Value{}, errors.New("expected true or false")
}
return schema.Bool(a.Bool), nil
case schema.KindInt32, schema.KindInt64:
if !num {
return schema.Value{}, errors.New("expected a number")
}
if fd.Kind == schema.KindInt32 {
return schema.Int32(int32(a.AsInt())), nil
}
return schema.Int64(a.AsInt()), nil
case schema.KindFloat32, schema.KindFloat64:
if !num {
return schema.Value{}, errors.New("expected a number")
}
if fd.Kind == schema.KindFloat32 {
return schema.Float32(float32(a.AsFloat())), nil
}
return schema.Float64(a.AsFloat()), nil
case schema.KindVec2:
f, err := numbers(a, 2)
if err != nil {
return schema.Value{}, err
}
return schema.Vec2(mathx.Vec2{X: f[0], Y: f[1]}), nil
case schema.KindColor:
f, err := numbers(a, 4)
if err != nil {
return schema.Value{}, err
}
return schema.Color(mathx.Color{R: f[0], G: f[1], B: f[2], A: f[3]}), nil
case schema.KindEnum:
switch a.Kind {
case aetext.VIdent:
if v, ok := fd.EnumValueOf(a.Ident); ok {
return schema.Enum(v), nil
}
return schema.Value{}, errors.New("unknown value " + a.Ident)
case aetext.VInt:
return schema.Enum(a.Int), nil
}
return schema.Value{}, errors.New("expected an enum name")
case schema.KindString:
if a.Kind != aetext.VString {
return schema.Value{}, errors.New("expected a string")
}
return schema.String(a.Str), nil
}
return schema.Value{}, errors.New("unsupported kind " + fd.Kind.String())
}