From e661c6546a6245d1729e8131a932341fe969650a Mon Sep 17 00:00:00 2001 From: 0xZens Date: Sat, 7 May 2022 19:45:34 +0800 Subject: [PATCH] Reuse underlying array if RawMessage has sufficient capacity This is a performance optimization for implementing cbor-patch. Signed-off-by: Yan Qing --- stream.go | 3 +-- stream_test.go | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/stream.go b/stream.go index 29172b92..05606e89 100644 --- a/stream.go +++ b/stream.go @@ -193,7 +193,6 @@ func (m *RawMessage) UnmarshalCBOR(data []byte) error { if m == nil { return errors.New("cbor.RawMessage: UnmarshalCBOR on nil pointer") } - *m = make([]byte, len(data)) - copy(*m, data) + *m = append((*m)[0:0], data...) return nil } diff --git a/stream_test.go b/stream_test.go index 6469628e..8d4282e7 100644 --- a/stream_test.go +++ b/stream_test.go @@ -5,6 +5,7 @@ package cbor import ( "bytes" + "fmt" "io" "reflect" "testing" @@ -387,6 +388,20 @@ func TestRawMessage(t *testing.T) { if !bytes.Equal(b, cborData) { t.Errorf("Marshal(%+v) = 0x%x, want 0x%x", v, b, cborData) } + + address := fmt.Sprintf("%p", *v.B) + if err := Unmarshal(v.A, v.B); err != nil { + t.Fatalf("Unmarshal(0x%x) returned error %v", v.A, err) + } + if address != fmt.Sprintf("%p", *v.B) { + t.Fatalf("Unmarshal RawMessage should reuse underlying array if it has sufficient capacity") + } + if err := Unmarshal(cborData, v.B); err != nil { + t.Fatalf("Unmarshal(0x%x) returned error %v", cborData, err) + } + if address == fmt.Sprintf("%p", *v.B) { + t.Fatalf("Unmarshal RawMessage should allocate a new underlying array if it does not have sufficient capacity") + } } func TestNullRawMessage(t *testing.T) {