Improve variable marshalling

This commit is contained in:
David Vogel 2024-12-02 11:52:05 +01:00
parent c730d437ef
commit bff2664cfc
3 changed files with 34 additions and 6 deletions

View File

@ -8,7 +8,7 @@ import (
var stderrRegex = regexp.MustCompile(`^error: (?<error>.+)\n ┌─ (?<path>.+):(?<line>\d+):(?<column>\d+)\n`)
// Error represents a typst error.
// Error represents a generic typst error.
type Error struct {
Inner error

View File

@ -4,6 +4,7 @@ import (
"encoding"
"fmt"
"io"
"math"
"reflect"
"slices"
"strconv"
@ -44,7 +45,9 @@ func (e *VariableEncoder) WriteIndentationCharacters() {
func (e *VariableEncoder) marshal(v reflect.Value) error {
if !v.IsValid() {
return fmt.Errorf("invalid reflect.Value %v", v)
e.WriteString("none")
return nil
//return fmt.Errorf("invalid reflect.Value %v", v)
}
t := v.Type()
@ -89,14 +92,24 @@ func (e *VariableEncoder) marshal(v reflect.Value) error {
e.WriteString(strconv.FormatInt(v.Int(), 10))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
e.WriteString(strconv.FormatUint(v.Uint(), 10))
case reflect.Float32:
e.WriteString(strconv.FormatFloat(v.Float(), 'e', -1, 32))
case reflect.Float64:
e.WriteString(strconv.FormatFloat(v.Float(), 'e', -1, 64))
case reflect.Float32, reflect.Float64:
f := v.Float()
switch {
case math.IsNaN(f):
e.WriteString("float.nan")
case math.IsInf(f, 1):
e.WriteString("float.inf")
case math.IsInf(f, -1):
e.WriteString("-float.inf")
default:
e.WriteString(strconv.FormatFloat(f, 'e', -1, 64))
}
case reflect.String:
return e.encodeString(v)
case reflect.Interface, reflect.Pointer:
return e.marshal(v.Elem())
case reflect.Map:
return e.encodeMap(v)
case reflect.Struct:
return e.encodeStruct(v, t)
case reflect.Slice:
@ -141,6 +154,11 @@ func (e *VariableEncoder) encodeString(v reflect.Value) error {
}
func (e *VariableEncoder) encodeStruct(v reflect.Value, t reflect.Type) error {
if v.NumField() == 0 {
e.WriteString("()")
return nil
}
e.WriteString("(\n")
e.indentLevel++
@ -187,6 +205,11 @@ func (e *VariableEncoder) resolveKeyName(v reflect.Value) (string, error) {
}
func (e *VariableEncoder) encodeMap(v reflect.Value) error {
if v.Len() == 0 {
e.WriteString("()")
return nil
}
e.WriteString("(\n")
e.indentLevel++

View File

@ -39,10 +39,15 @@ func TestVariableEncoder(t *testing.T) {
Foo string
Bar int
}{"Hey!", 12345}, false, "(\n Foo: \"Hey!\",\n Bar: 12345,\n)"},
{"struct empty", struct{}{}, false, "()"},
{"struct empty pointer", (*struct{})(nil), false, "none"},
{"map string string", map[string]string{"Foo": "Bar", "Foo2": "Electric Foogaloo"}, false, "(\n Foo: \"Bar\",\n Foo2: \"Electric Foogaloo\",\n)"},
{"map string string empty", map[string]string{}, false, "()"},
{"map string string nil", map[string]string(nil), false, "()"},
{"string array", [5]string{"Foo", "Bar"}, false, `("Foo", "Bar", "", "", "")`},
{"string slice", []string{"Foo", "Bar"}, false, `("Foo", "Bar")`},
{"string slice empty", []string{}, false, `()`},
{"string slice nil", []string(nil), false, `()`},
{"string slice pointer", &[]string{"Foo", "Bar"}, false, `("Foo", "Bar")`},
}
for _, tt := range tests {