From 73ab63da063748f7bc295f6f24d682a38e87d344 Mon Sep 17 00:00:00 2001 From: Yanhu007 Date: Tue, 14 Apr 2026 07:06:05 +0800 Subject: [PATCH] fix: encode non-addressable values with pointer receiver methods When encoding a value type that implements CustomEncoder, encoding.BinaryMarshaler, or encoding.TextMarshaler via pointer receivers, the encoder returns an unhelpful error if the value is not addressable (e.g. returned directly from a function or stored in an interface). Instead of returning an error, allocate a temporary addressable copy of the value and encode through that. This matches how encoding/json handles the same situation. Fixes #374 --- encode_value.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/encode_value.go b/encode_value.go index 1d6303a..10b3bcd 100644 --- a/encode_value.go +++ b/encode_value.go @@ -134,7 +134,9 @@ func ptrEncoderFunc(typ reflect.Type) encoderFunc { func encodeCustomValuePtr(e *Encoder, v reflect.Value) error { if !v.CanAddr() { - return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) + vp := reflect.New(v.Type()) + vp.Elem().Set(v) + v = vp.Elem() } encoder := v.Addr().Interface().(CustomEncoder) return encoder.EncodeMsgpack(e) @@ -151,7 +153,9 @@ func encodeCustomValue(e *Encoder, v reflect.Value) error { func marshalValuePtr(e *Encoder, v reflect.Value) error { if !v.CanAddr() { - return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) + vp := reflect.New(v.Type()) + vp.Elem().Set(v) + v = vp.Elem() } return marshalValue(e, v.Addr()) } @@ -211,7 +215,9 @@ func nilableType(t reflect.Type) bool { func marshalBinaryValueAddr(e *Encoder, v reflect.Value) error { if !v.CanAddr() { - return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) + vp := reflect.New(v.Type()) + vp.Elem().Set(v) + v = vp.Elem() } return marshalBinaryValue(e, v.Addr()) } @@ -234,7 +240,9 @@ func marshalBinaryValue(e *Encoder, v reflect.Value) error { func marshalTextValueAddr(e *Encoder, v reflect.Value) error { if !v.CanAddr() { - return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface()) + vp := reflect.New(v.Type()) + vp.Elem().Set(v) + v = vp.Elem() } return marshalTextValue(e, v.Addr()) }