diff --git a/vmap/encoder_fast.go b/vmap/encoder_fast.go index 589e00c..c24e240 100644 --- a/vmap/encoder_fast.go +++ b/vmap/encoder_fast.go @@ -6,18 +6,30 @@ import ( // MarshalVmap marshals a VMAP to XML, producing output identical to encoding/xml.Marshal. func MarshalVmap(v *VMAP) ([]byte, error) { - buf := make([]byte, 0, 8192) + buf := make([]byte, 0, 256*1024) buf = appendVMAP(buf, v) return buf, nil } +// MarshalVmapAppend appends the XML encoding of a VMAP to buf and returns the extended buffer. +// This allows callers to manage buffer lifecycle (e.g. via sync.Pool) for reduced allocations. +func MarshalVmapAppend(buf []byte, v *VMAP) ([]byte, error) { + return appendVMAP(buf, v), nil +} + // MarshalVast marshals a VAST to XML, producing output identical to encoding/xml.Marshal. func MarshalVast(v *VAST) ([]byte, error) { - buf := make([]byte, 0, 4096) + buf := make([]byte, 0, 128*1024) buf = appendVAST(buf, v) return buf, nil } +// MarshalVastAppend appends the XML encoding of a VAST to buf and returns the extended buffer. +// This allows callers to manage buffer lifecycle (e.g. via sync.Pool) for reduced allocations. +func MarshalVastAppend(buf []byte, v *VAST) ([]byte, error) { + return appendVAST(buf, v), nil +} + // --- escape helpers --- // escText escapes text content, matching encoding/xml.EscapeText. diff --git a/vmap/structure_test.go b/vmap/structure_test.go index 5966575..42733eb 100644 --- a/vmap/structure_test.go +++ b/vmap/structure_test.go @@ -572,6 +572,65 @@ func TestMarshalSpecialCharsFast(t *testing.T) { is.Equal(string(expected), string(got)) } +// --- MarshalAppend Tests --- + +func TestMarshalVmapAppend(t *testing.T) { + is := is.New(t) + doc, err := os.ReadFile("sample-vmap/testVmap.xml") + is.NoErr(err) + + var v VMAP + err = xml.Unmarshal(doc, &v) + is.NoErr(err) + + expected, err := MarshalVmap(&v) + is.NoErr(err) + + buf := make([]byte, 0, 1024) + got, err := MarshalVmapAppend(buf, &v) + is.NoErr(err) + + is.Equal(string(expected), string(got)) +} + +func TestMarshalVastAppend(t *testing.T) { + is := is.New(t) + doc, err := os.ReadFile("sample-vmap/testVast.xml") + is.NoErr(err) + + var v VAST + err = xml.Unmarshal(doc, &v) + is.NoErr(err) + + expected, err := MarshalVast(&v) + is.NoErr(err) + + buf := make([]byte, 0, 1024) + got, err := MarshalVastAppend(buf, &v) + is.NoErr(err) + + is.Equal(string(expected), string(got)) +} + +func TestMarshalVmapAppendPreservesPrefix(t *testing.T) { + is := is.New(t) + doc, err := os.ReadFile("sample-vmap/testVmap.xml") + is.NoErr(err) + + var v VMAP + err = xml.Unmarshal(doc, &v) + is.NoErr(err) + + prefix := []byte("PREFIX") + buf := make([]byte, len(prefix), 1024) + copy(buf, prefix) + + got, err := MarshalVmapAppend(buf, &v) + is.NoErr(err) + + is.Equal(string(got[:len(prefix)]), "PREFIX") +} + // --- Fast Marshal Benchmarks --- func BenchmarkXMLMarshalVmap(b *testing.B) {