mirror of
https://github.com/luxfi/chains.git
synced 2026-09-24 00:26:00 +00:00
quantumvm registered node's JSON-RPC codec — the one that raises the initial of the function named after the dot. That codec is now internal/codec, so the spelling quantumvm serves, quantumvm.getBlock for Service.GetBlock, is decided in this module. The spelling is unchanged: an initial that is already upper-case is refused, and an argument that will not read reports one message. identityvm, keyvm and bridgevm register gorilla's plain codec and keep it. Co-authored-by: Hanzo Dev <[email protected]>
73 lines
2.2 KiB
Go
73 lines
2.2 KiB
Go
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Package codec speaks the JSON-RPC spelling this repo's VMs serve. A client
|
|
// names a method as class.function with a lower-case initial, and the codec
|
|
// hands the server the exported Go method that answers it, so
|
|
// quantumvm.getBlock reaches Service.GetBlock.
|
|
//
|
|
// A function whose initial is already upper-case is refused, so exactly one
|
|
// spelling reaches a service.
|
|
package codec
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
|
|
"github.com/gorilla/rpc/v2"
|
|
"github.com/gorilla/rpc/v2/json2"
|
|
)
|
|
|
|
var (
|
|
errUppercaseMethod = errors.New("method must start with a non-uppercase letter")
|
|
errInvalidArg = errors.New("couldn't unmarshal an argument. Ensure arguments are valid and properly formatted. See documentation for example calls")
|
|
)
|
|
|
|
// New returns a JSON-RPC codec that raises the initial of the function named
|
|
// after the dot.
|
|
func New() rpc.Codec {
|
|
return codec{json2.NewCodec()}
|
|
}
|
|
|
|
type codec struct{ *json2.Codec }
|
|
|
|
func (c codec) NewRequest(r *http.Request) rpc.CodecRequest {
|
|
return &request{c.Codec.NewRequest(r).(*json2.CodecRequest)}
|
|
}
|
|
|
|
type request struct{ *json2.CodecRequest }
|
|
|
|
// Method names the Go method the request asks for: the class unchanged, and
|
|
// the function with its initial raised. A name carrying no dot, or one whose
|
|
// initial is not a rune, is passed through as it arrived.
|
|
func (r *request) Method() (string, error) {
|
|
method, err := r.CodecRequest.Method()
|
|
parts := strings.SplitN(method, ".", 2)
|
|
if len(parts) != 2 || err != nil {
|
|
return method, err
|
|
}
|
|
class, function := parts[0], parts[1]
|
|
initial, size := utf8.DecodeRuneInString(function)
|
|
if initial == utf8.RuneError {
|
|
return method, nil
|
|
}
|
|
if unicode.IsUpper(initial) {
|
|
return method, errUppercaseMethod
|
|
}
|
|
raised := string(unicode.ToUpper(initial))
|
|
return fmt.Sprintf("%s.%s%s", class, raised, function[size:]), nil
|
|
}
|
|
|
|
// ReadRequest reports one message for arguments it cannot read, so a caller
|
|
// learns its arguments are wrong and nothing further.
|
|
func (r *request) ReadRequest(args any) error {
|
|
if err := r.CodecRequest.ReadRequest(args); err != nil {
|
|
return errInvalidArg
|
|
}
|
|
return nil
|
|
}
|