@@ -3,19 +3,31 @@ package metadata
33import (
44 "encoding/json"
55
6+ "github.com/mailru/easyjson"
67 "github.com/mailru/easyjson/jlexer"
8+ "github.com/mailru/easyjson/jwriter"
9+ "github.com/pkg/errors"
710)
811
9- // Metadata is an immutable map[string]interface{} implementation
10- type Metadata interface {
11- // Value returns the value associated with this context for key, or nil
12- // if no value is associated with key. Successive calls to Value with
13- // the same key returns the same result.
14- Value (key string ) interface {}
12+ type (
13+ // Metadata is an immutable map[string]interface{} implementation
14+ Metadata interface {
15+ // Value returns the value associated with this context for key, or nil
16+ // if no value is associated with key. Successive calls to Value with
17+ // the same key returns the same result.
18+ Value (key string ) interface {}
1519
16- // AsMap return the Metadata as a map[string]interface{}
17- AsMap () map [string ]interface {}
18- }
20+ // AsMap return the Metadata as a map[string]interface{}
21+ AsMap () map [string ]interface {}
22+ }
23+
24+ // jsonMarshaler is an interface used to speed up the json marshalling process
25+ jsonMarshaler interface {
26+ // MarshalJSONKeyValue writes the Metadata Key and Value and all it's parent Key Value pairs into the writer
27+ // If last is true it MUST omit the `,` from the last Key Value pair
28+ MarshalJSONKeyValue (out * jwriter.Writer , last bool )
29+ }
30+ )
1931
2032// New return a new Metadata instance without any information
2133func New () Metadata {
@@ -43,8 +55,12 @@ type emptyData int
4355var (
4456 // Ensure emptyData implements the Metadata interface
4557 _ Metadata = new (emptyData )
46- // Ensure valueData implements the json.Marshaler interface
58+ // Ensure valueData implements the jsonMarshaler interface
59+ _ jsonMarshaler = new (emptyData )
60+ // Ensure emptyData implements the json.Marshaler interface
4761 _ json.Marshaler = new (emptyData )
62+ // Ensure emptyData implements the easyjson.Marshaler interface
63+ _ easyjson.Marshaler = new (emptyData )
4864)
4965
5066func (* emptyData ) Value (key string ) interface {} {
@@ -59,6 +75,14 @@ func (v *emptyData) MarshalJSON() ([]byte, error) {
5975 return []byte ("{}" ), nil
6076}
6177
78+ func (v * emptyData ) MarshalEasyJSON (w * jwriter.Writer ) {
79+ w .RawByte ('{' )
80+ w .RawByte ('}' )
81+ }
82+
83+ func (v * emptyData ) MarshalJSONKeyValue (* jwriter.Writer , bool ) {
84+ }
85+
6286// valueData represents a key, value pair in a metadata chain
6387type valueData struct {
6488 Metadata
@@ -69,8 +93,12 @@ type valueData struct {
6993var (
7094 // Ensure valueData implements the Metadata interface
7195 _ Metadata = new (valueData )
96+ // Ensure valueData implements the jsonMarshaler interface
97+ _ jsonMarshaler = new (valueData )
7298 // Ensure valueData implements the json.Marshaler interface
7399 _ json.Marshaler = new (valueData )
100+ // Ensure valueData implements the easyjson.Marshaler interface
101+ _ easyjson.Marshaler = new (valueData )
74102)
75103
76104func (v * valueData ) Value (key string ) interface {} {
@@ -95,7 +123,33 @@ func (v *valueData) AsMap() map[string]interface{} {
95123}
96124
97125func (v * valueData ) MarshalJSON () ([]byte , error ) {
98- return json .Marshal (v .AsMap ())
126+ w := jwriter.Writer {}
127+ v .MarshalEasyJSON (& w )
128+ return w .Buffer .BuildBytes (), w .Error
129+ }
130+
131+ func (v * valueData ) MarshalEasyJSON (w * jwriter.Writer ) {
132+ w .RawByte ('{' )
133+ v .MarshalJSONKeyValue (w , true )
134+ w .RawByte ('}' )
135+ }
136+
137+ func (v * valueData ) MarshalJSONKeyValue (out * jwriter.Writer , last bool ) {
138+ marshalJSONKeyValues (out , v .Metadata )
139+
140+ out .String (v .key )
141+ out .RawByte (':' )
142+ if vm , ok := v .val .(easyjson.Marshaler ); ok {
143+ vm .MarshalEasyJSON (out )
144+ } else if vm , ok := v .val .(json.Marshaler ); ok {
145+ out .Raw (vm .MarshalJSON ())
146+ } else {
147+ out .Raw (json .Marshal (v .val ))
148+ }
149+
150+ if ! last {
151+ out .RawByte (',' )
152+ }
99153}
100154
101155// UnmarshalJSON unmarshals the provided json into a Metadata instance
@@ -127,3 +181,42 @@ func UnmarshalJSON(json []byte) (Metadata, error) {
127181
128182 return metadata , in .Error ()
129183}
184+
185+ func marshalJSONKeyValues (out * jwriter.Writer , parent Metadata ) {
186+ if parent == nil {
187+ return
188+ }
189+
190+ if m , ok := parent .(jsonMarshaler ); ok {
191+ m .MarshalJSONKeyValue (out , false )
192+ return
193+ }
194+
195+ var (
196+ parentJSON []byte
197+ err error
198+ )
199+ if vm , ok := parent .(easyjson.Marshaler ); ok {
200+ w := & jwriter.Writer {}
201+ vm .MarshalEasyJSON (out )
202+ parentJSON = w .Buffer .BuildBytes ()
203+ err = w .Error
204+ } else if vm , ok := parent .(json.Marshaler ); ok {
205+ parentJSON , err = vm .MarshalJSON ()
206+ } else {
207+ parentJSON , err = json .Marshal (parent )
208+ }
209+
210+ if err != nil {
211+ out .Raw (parentJSON , err )
212+ return
213+ }
214+
215+ plen := len (parentJSON )
216+ if parentJSON [1 ] != '{' || parentJSON [plen - 1 ] != '}' {
217+ out .Raw (parentJSON , errors .Errorf ("JSON unmarshal failed for Metadata of type %T" , parent ))
218+ return
219+ }
220+
221+ out .Raw (parentJSON [1 :plen - 2 ], nil )
222+ }
0 commit comments