feat!: rework the public API to json/v2-style variadic options
Test / test (push) Successful in 1m49s

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-22 18:42:18 +02:00
parent 7ee155d1e9
commit 2e61ad0ba9
18 changed files with 398 additions and 393 deletions
+30 -34
View File
@@ -91,9 +91,6 @@ func TestMarshalContextHonoursCancellation(t *testing.T) {
if _, err := MarshalContext(ctx, C{A: 1}); !errors.Is(err, context.Canceled) {
t.Fatalf("MarshalContext returned %v, want context.Canceled", err)
}
if _, err := NewEncoder().MarshalContext(ctx, C{A: 1}); !errors.Is(err, context.Canceled) {
t.Fatalf("Encoder.MarshalContext returned %v, want context.Canceled", err)
}
}
func TestEncoderLayoutGroupedDefault(t *testing.T) {
@@ -105,7 +102,7 @@ func TestEncoderLayoutGroupedDefault(t *testing.T) {
Host string `toml:"host"`
} `toml:"s"`
}
out, err := NewEncoder().Marshal(Cfg{Name: "x", S: struct {
out, err := Marshal(Cfg{Name: "x", S: struct {
Host string `toml:"host"`
}{Host: "h"}})
if err != nil {
@@ -131,7 +128,7 @@ func TestEncoderLayoutDeclarationPreservesOrder(t *testing.T) {
Server: Inner{Host: "h"},
Debug: true,
}
out, err := NewEncoder().Layout(LayoutKindDeclaration).Marshal(in)
out, err := Marshal(in, Layout(LayoutKindDeclaration))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -161,7 +158,7 @@ func TestEncoderLayoutGroupedDefaultOrder(t *testing.T) {
Server: Inner{Host: "h"},
Debug: true,
}
out, err := NewEncoder().Marshal(in)
out, err := Marshal(in)
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -176,10 +173,10 @@ func TestEncoderOmitEmptyArrays(t *testing.T) {
Tags []string `toml:"tags"`
Secrets []string `toml:"secrets"`
}
out, err := NewEncoder().OmitEmptyArrays().Marshal(Cfg{
out, err := Marshal(Cfg{
Tags: []string{"a", "b"},
Secrets: []string{},
})
}, OmitEmptyArrays(true))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -193,7 +190,7 @@ func TestEncoderDefaultEmitsEmptyArray(t *testing.T) {
type Cfg struct {
Tags []string `toml:"tags"`
}
out, err := NewEncoder().Marshal(Cfg{Tags: []string{}})
out, err := Marshal(Cfg{Tags: []string{}})
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -211,10 +208,10 @@ func TestEncoderOmitEmptyArrayOfTablesStillSkipped(t *testing.T) {
Title string `toml:"title"`
Items []Item `toml:"items"`
}
out, err := NewEncoder().OmitEmptyArrays().Marshal(Cfg{
out, err := Marshal(Cfg{
Title: "demo",
Items: nil,
})
}, OmitEmptyArrays(true))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -229,7 +226,7 @@ func TestEncoderLiteralMultiline(t *testing.T) {
Long string `toml:"long"`
}
long := strings.Repeat("a", 50) + "\nline two\nline three"
out, err := NewEncoder().LiteralMultiline(20).Marshal(Cfg{Long: long})
out, err := Marshal(Cfg{Long: long}, LiteralMultiline(20))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -244,7 +241,7 @@ func TestEncoderLiteralMultilineBelowThreshold(t *testing.T) {
type Cfg struct {
Short string `toml:"short"`
}
out, err := NewEncoder().LiteralMultiline(1000).Marshal(Cfg{Short: "one\ntwo"})
out, err := Marshal(Cfg{Short: "one\ntwo"}, LiteralMultiline(1000))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -259,7 +256,7 @@ func TestEncoderLiteralMultilineThresholdZero(t *testing.T) {
type Cfg struct {
S string `toml:"s"`
}
out, err := NewEncoder().LiteralMultiline(0).Marshal(Cfg{S: "a\nb\nc\nd"})
out, err := Marshal(Cfg{S: "a\nb\nc\nd"}, LiteralMultiline(0))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -282,7 +279,7 @@ func TestEncoderLiteralMultilineFallsBackWhenUnsafe(t *testing.T) {
{"lone carriage return", "first\rsecond\nthird"},
}
for _, c := range cases {
out, err := NewEncoder().LiteralMultiline(5).Marshal(map[string]any{"s": c.in})
out, err := Marshal(map[string]any{"s": c.in}, LiteralMultiline(5))
if err != nil {
t.Fatalf("%s: marshal: %v", c.name, err)
}
@@ -482,11 +479,10 @@ func TestEncoderChainedOptions(t *testing.T) {
I Inner `toml:"i"`
}
long := strings.Repeat("x", 200)
out, err := NewEncoder().
Layout(LayoutKindDeclaration).
OmitEmptyArrays().
LiteralMultiline(50).
Marshal(Cfg{S: "short", I: Inner{V: long}})
out, err := Marshal(Cfg{S: "short", I: Inner{V: long}},
Layout(LayoutKindDeclaration),
OmitEmptyArrays(true),
LiteralMultiline(50))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -1302,7 +1298,7 @@ func TestEncoderEquivalenceToMarshal(t *testing.T) {
if err != nil {
t.Fatalf("marshal: %v", err)
}
b, err := NewEncoder().Marshal(in)
b, err := Marshal(in)
if err != nil {
t.Fatalf("encoder marshal: %v", err)
}
@@ -1710,7 +1706,7 @@ func TestEncoderInlineTables(t *testing.T) {
// With the option both fit the threshold and become inline tables, nested
// ones included.
out, err := NewEncoder().InlineTables(60).Marshal(cfg)
out, err := Marshal(cfg, InlineTables(60))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -1720,7 +1716,7 @@ func TestEncoderInlineTables(t *testing.T) {
}
// A threshold below the rendering keeps the header form.
out, err = NewEncoder().InlineTables(10).Marshal(cfg)
out, err = Marshal(cfg, InlineTables(10))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -1749,7 +1745,7 @@ func TestEncoderInlineTablesOrderAndRoundTrip(t *testing.T) {
if err != nil {
t.Fatalf("marshal: %v", err)
}
compact, err := NewEncoder().InlineTables(20).Marshal(cfg)
compact, err := Marshal(cfg, InlineTables(20))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -1785,7 +1781,7 @@ func TestEncoderInlineTablesKeepsArraysOfTables(t *testing.T) {
Small inlineTLS `toml:"small"`
}
cfg := Cfg{Items: []Item{{N: 1}}, Small: inlineTLS{On: true}}
out, err := NewEncoder().InlineTables(60).Marshal(cfg)
out, err := Marshal(cfg, InlineTables(60))
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -1973,7 +1969,7 @@ func TestMarshalNumber(t *testing.T) {
t.Fatalf("output %q", out)
}
var back map[string]any
if err := NewDecoder().UseNumber().Decode(out, &back); err != nil {
if err := Unmarshal(out, &back, NumbersAsLiterals(true)); err != nil {
t.Fatal(err)
}
if got, ok := back["rate"].(Number); !ok || got != "1_000" {
@@ -2073,7 +2069,7 @@ func TestMarshalCyclicData(t *testing.T) {
})
}
func TestUnmarshalWithOptions(t *testing.T) {
func TestUnmarshalOptionsShape(t *testing.T) {
data := []byte("host = \"db\"\nextra = 1\n")
type Config struct {
Host string `toml:"host,required"`
@@ -2083,7 +2079,7 @@ func TestUnmarshalWithOptions(t *testing.T) {
Host string `toml:"host"`
Extra int `toml:"extra"`
}
if err := UnmarshalWithOptions(data, &cfg, DecodeOptions{}); err != nil {
if err := Unmarshal(data, &cfg); err != nil {
t.Fatal(err)
}
if cfg.Host != "db" || cfg.Extra != 1 {
@@ -2091,7 +2087,7 @@ func TestUnmarshalWithOptions(t *testing.T) {
}
})
t.Run("strict and required work in one call", func(t *testing.T) {
err := UnmarshalWithOptions(data, &Config{}, DecodeOptions{DisallowUnknownFields: true})
err := Unmarshal(data, &Config{}, RejectUnknownFields(true))
want := `interpres: unknown field "extra" for interpres.Config`
if err == nil || err.Error() != want {
t.Errorf("err = %v, want %q", err, want)
@@ -2100,7 +2096,7 @@ func TestUnmarshalWithOptions(t *testing.T) {
t.Run("UseNumber keeps the literal", func(t *testing.T) {
var tree map[string]any
in := []byte("n = 1_000\n")
if err := UnmarshalWithOptions(in, &tree, DecodeOptions{UseNumber: true}); err != nil {
if err := Unmarshal(in, &tree, NumbersAsLiterals(true)); err != nil {
t.Fatal(err)
}
if got, ok := tree["n"].(Number); !ok || got != "1_000" {
@@ -2118,10 +2114,10 @@ func TestUnmarshalWithOptions(t *testing.T) {
nested.WriteString("]")
}
var tree map[string]any
if err := UnmarshalWithOptions([]byte(nested.String()), &tree, DecodeOptions{MaxDepth: 10}); err == nil {
if err := Unmarshal([]byte(nested.String()), &tree, MaxNestingDepth(10)); err == nil {
t.Error("a document over MaxDepth decoded, want an error")
}
if err := UnmarshalWithOptions([]byte("a = 1\n"), &tree, DecodeOptions{MaxInputSize: 2}); err == nil {
if err := Unmarshal([]byte("a = 1\n"), &tree, MaxInputSize(2)); err == nil {
t.Error("a document over MaxInputSize decoded, want an error")
}
})
@@ -2253,7 +2249,7 @@ func TestEmitFieldComments(t *testing.T) {
}
})
t.Run("on, the comments print above their lines", func(t *testing.T) {
out, err := NewEncoder().EmitFieldComments().Marshal(cfg)
out, err := Marshal(cfg, EmitFieldComments(true))
if err != nil {
t.Fatal(err)
}
@@ -2278,7 +2274,7 @@ func TestEmitFieldComments(t *testing.T) {
type Nested struct {
Inner Inner `toml:"inner,comment=The inner table"`
}
out, err := NewEncoder().EmitFieldComments().Marshal(Nested{Inner: Inner{1}})
out, err := Marshal(Nested{Inner: Inner{1}}, EmitFieldComments(true))
if err != nil {
t.Fatal(err)
}