neoneo-go/pkg/services/rpcsrv/params/types.go

112 lines
2.4 KiB
Go
Raw Normal View History

package params
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"github.com/nspcc-dev/neo-go/pkg/neorpc"
)
const (
// maxBatchSize is the maximum number of requests per batch.
maxBatchSize = 100
)
// Request contains standard JSON-RPC 2.0 request and batch of
// requests: http://www.jsonrpc.org/specification.
// It's used in server to represent incoming queries.
type Request struct {
In *In
Batch Batch
}
// In represents a standard JSON-RPC 2.0
// request: http://www.jsonrpc.org/specification#request_object.
type In struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
RawParams []Param `json:"params,omitempty"`
RawID json.RawMessage `json:"id,omitempty"`
}
// Batch represents a standard JSON-RPC 2.0
// batch: https://www.jsonrpc.org/specification#batch.
type Batch []In
// MarshalJSON implements the json.Marshaler interface.
func (r Request) MarshalJSON() ([]byte, error) {
if r.In != nil {
return json.Marshal(r.In)
}
return json.Marshal(r.Batch)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (r *Request) UnmarshalJSON(data []byte) error {
var (
in *In
batch Batch
)
in = &In{}
err := json.Unmarshal(data, in)
if err == nil {
r.In = in
return nil
}
decoder := json.NewDecoder(bytes.NewReader(data))
t, err := decoder.Token() // read `[`
if err != nil {
return err
}
if t != json.Delim('[') {
return fmt.Errorf("`[` expected, got %s", t)
}
count := 0
for decoder.More() {
if count > maxBatchSize {
return fmt.Errorf("the number of requests in batch shouldn't exceed %d", maxBatchSize)
}
in = &In{}
decodeErr := decoder.Decode(in)
if decodeErr != nil {
return decodeErr
}
batch = append(batch, *in)
count++
}
if len(batch) == 0 {
return errors.New("empty request")
}
r.Batch = batch
return nil
}
// DecodeData decodes the given reader into the the request
// struct.
func (r *Request) DecodeData(data io.ReadCloser) error {
defer data.Close()
rawData := json.RawMessage{}
err := json.NewDecoder(data).Decode(&rawData)
if err != nil {
return fmt.Errorf("error parsing JSON payload: %w", err)
}
return r.UnmarshalJSON(rawData)
}
// NewRequest creates a new Request struct.
func NewRequest() *Request {
return &Request{}
}
// NewIn creates a new In struct.
func NewIn() *In {
return &In{
JSONRPC: neorpc.JSONRPCVersion,
}
}