good morning!!!!

Skip to content
Snippets Groups Projects
Select Git revision
  • 00d78f820129fbb2b7cd066e58a32b153dd3490d
  • master default protected
  • add-tests
  • extensions
  • gateway
  • codec-bundle
  • renovate/github.com-gfx-labs-sse-digest
  • renovate/golang.org-x-net-0.x
  • renovate/golang-1.x
  • jsonv2
  • garet
  • check
  • http-curse
  • whatthefuck
  • pool
  • envelope
  • mod
  • simplify
  • new-interface
  • v2
  • master-old
  • v0.8.0
  • v0.7.0
  • v0.6.1
  • v0.6.0
  • v0.5.4
  • v0.5.3
  • v0.5.2
  • v0.5.1
  • v0.5.0
  • v0.4.19
  • v0.4.18
  • v0.4.17
  • v0.4.16
  • v0.4.15
  • v0.4.14
  • v0.4.13
  • v0.4.12
  • v0.4.11
  • v0.4.10
  • v0.4.9
41 results

json.go

Blame
  • a's avatar
    a authored
    00d78f82
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    json.go 5.86 KiB
    package codec
    
    import (
    	"bytes"
    	"encoding/json"
    	"fmt"
    	"strconv"
    
    	"github.com/go-faster/jx"
    )
    
    var Null = json.RawMessage("null")
    
    func NewNull() json.RawMessage {
    	return json.RawMessage("null")
    }
    
    type ExtraFields map[string]json.RawMessage
    
    // A value of this type can a JSON-RPC request, notification, successful response or
    // error response. Which one it is depends on the fields.
    type Message struct {
    	ID     *ID             `json:"id,omitempty"`
    	Method string          `json:"method,omitempty"`
    	Params json.RawMessage `json:"params,omitempty"`
    	Result json.RawMessage `json:"result,omitempty"`
    	Error  error           `json:"error,omitempty"`
    
    	ExtraFields ExtraFields `json:"-"`
    }
    
    func MarshalMessage(m *Message, enc *jx.Encoder) error {
    	// use encoder
    	fail := enc.Obj(func(e *jx.Encoder) {
    		e.Field("jsonrpc", func(e *jx.Encoder) {
    			e.Str("2.0")
    		})
    		if m.ID != nil {
    			e.Field("id", func(e *jx.Encoder) {
    				e.Raw(m.ID.RawMessage())
    			})
    		}
    		if m.Method != "" {
    			e.Field("method", func(e *jx.Encoder) {
    				e.Str(m.Method)
    			})
    		}
    		for k, v := range m.ExtraFields {
    			e.Field(k, func(e *jx.Encoder) {
    				e.Raw(v)
    			})
    		}
    		if m.Error != nil {
    			e.Field("error", func(e *jx.Encoder) {
    				EncodeError(e, m.Error)
    			})
    			return
    		}
    		if len(m.Params) != 0 {
    			e.Field("params", func(e *jx.Encoder) {
    				e.Raw(m.Params)
    			})
    		}
    		if len(m.Result) != 0 {
    			e.Field("result", func(e *jx.Encoder) {
    				e.Raw(m.Result)
    			})
    		}
    	})
    	if fail {
    		return fmt.Errorf("jx encoding error")
    	}
    	// output
    	return nil
    }
    
    func UnmarshalMessage(m *Message, dec *jx.Decoder) error {
    	err := dec.Obj(func(d *jx.Decoder, key string) (err error) {
    		switch key {
    		default:
    			val, err := d.Raw()
    			if err != nil {
    				return err
    			}
    			buf := bytes.NewBuffer(make(json.RawMessage, len(val)))
    			buf.Write(val)
    			if m.ExtraFields == nil {
    				m.ExtraFields = ExtraFields{}
    			}
    			m.ExtraFields[key] = buf.Bytes()
    		case "jsonrpc":
    			value, err := d.Str()
    			if err != nil {
    				return err
    			}
    			if value != VersionString {
    				return NewInvalidRequestError("Invalid Version")
    			}
    		case "id":
    			raw, err := d.Raw()
    			if err != nil {
    				return err
    			}
    			id := &ID{}
    			err = id.UnmarshalJSON(raw)
    			m.ID = id
    			if err != nil {
    				return err
    			}
    		case "method":
    			m.Method, err = d.Str()
    		case "params":
    			val, err := d.Raw()
    			if err != nil {
    				return err
    			}
    			buf := bytes.NewBuffer(m.Params)
    			buf.Reset()
    			_, err = buf.Write(val)
    			if err != nil {
    				return err
    			}
    			m.Params = buf.Bytes()
    		case "result":
    			val, err := d.Raw()
    			if err != nil {
    				return err
    			}
    			buf := bytes.NewBuffer(m.Result)
    			buf.Reset()
    			_, err = buf.Write(val)
    			if err != nil {
    				return err
    			}
    			m.Result = buf.Bytes()
    		case "error":
    			val, err := d.Raw()
    			if err != nil {
    				return err
    			}
    			m.Error = &JsonError{}
    			err = json.Unmarshal(val, m.Error)
    			if err != nil {
    				return err
    			}
    		}
    		return err
    	})
    	if err != nil {
    		return err
    	}
    	return nil
    }
    
    func (m *Message) UnmarshalJSON(xs []byte) error {
    	dec := jx.GetDecoder()
    	defer jx.PutDecoder(dec)
    	dec.ResetBytes(xs)
    	return UnmarshalMessage(m, dec)
    }
    
    func (m Message) MarshalJSON() ([]byte, error) {
    	buf := &bytes.Buffer{}
    	enc := jx.NewStreamingEncoder(buf, 4096)
    	err := MarshalMessage(&m, enc)
    	if err != nil {
    		return nil, err
    	}
    	err = enc.Close()
    	if err != nil {
    		return nil, err
    	}
    	return buf.Bytes(), nil
    }
    
    func (msg *Message) String() string {
    	b, _ := msg.MarshalJSON()
    	return string(b)
    }
    
    // encapsulate json rpc error into struct
    type JsonError struct {
    	Code    int    `json:"code"`
    	Message string `json:"message"`
    	Data    any    `json:"data,omitempty"`
    }
    
    func (err *JsonError) Error() string {
    	if err.Message == "" {
    		return "json-rpc error " + strconv.Itoa(err.Code)
    	}
    	return err.Message
    }
    
    func (err *JsonError) ErrorCode() int {
    	return err.Code
    }
    
    func (err *JsonError) ErrorData() any {
    	return err.Data
    }
    
    // isBatch returns true when the first non-whitespace characters is '['
    func IsBatchMessage(raw json.RawMessage) bool {
    	for _, c := range raw {
    		// skip insignificant whitespace (http://www.ietf.org/rfc/rfc4627.txt)
    		switch c {
    		case 0x20, 0x09, 0x0a, 0x0d:
    			continue
    		}
    		return c == '['
    	}
    	return false
    }
    
    func (m ExtraFields) SetExtraField(name string, v any) (err error) {
    	switch name {
    	case "id", "jsonrpc", "method", "params", "result", "error":
    		return fmt.Errorf("%w: %q", ErrIllegalExtraField, name)
    	}
    	if v == nil {
    		delete(m, name)
    	}
    	val, err := json.Marshal(v)
    	if err != nil {
    		return err
    	}
    	m[name] = val
    	return nil
    }
    func (m ExtraFields) Clear() {
    	for k := range m {
    		delete(m, k)
    	}
    }
    
    func (m *Message) SetExtraField(name string, v any) error {
    	return m.ExtraFields.SetExtraField(name, v)
    }
    
    // parseMessage parses raw bytes as a (batch of) JSON-RPC message(s). There are no error
    // checks in this function because the raw message has already been syntax-checked when it
    // is called. Any non-JSON-RPC messages in the input return the zero value of
    // Message.
    func ParseMessage(in json.RawMessage) ([]*Message, bool) {
    	return ReadMessage(jx.DecodeBytes(in))
    
    }
    
    // parseMessage parses raw bytes as a (batch of) JSON-RPC message(s). There are no error
    // checks in this function because the raw message has already been syntax-checked when it
    // is called. Any non-JSON-RPC messages in the input return the zero value of
    // Message.
    func ReadMessage(dec *jx.Decoder) ([]*Message, bool) {
    	msgs := []*Message{{}}
    
    	switch dec.Next() {
    	case jx.Object:
    		_ = UnmarshalMessage(msgs[0], dec)
    		return msgs, false
    	default:
    		return msgs, false
    	case jx.Array:
    		msgs = []*Message{}
    		dec.Arr(func(d *jx.Decoder) error {
    			msg := new(Message)
    			//err := UnmarshalMessage(msg, d)
    			raw, err := d.Raw()
    			if err != nil {
    				raw = []byte{}
    			}
    			err = json.Unmarshal(raw, msg)
    			if err != nil {
    				msg = nil
    			}
    			msgs = append(msgs, msg)
    			return nil
    		})
    		return msgs, true
    	}
    }