github.com/MetalBlockchain/metalgo@v1.11.9/utils/json/codec.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package json 5 6 import ( 7 "errors" 8 "fmt" 9 "net/http" 10 "strings" 11 "unicode" 12 "unicode/utf8" 13 14 "github.com/gorilla/rpc/v2" 15 "github.com/gorilla/rpc/v2/json2" 16 ) 17 18 const ( 19 // Null is the string representation of a null value 20 Null = "null" 21 ) 22 23 var ( 24 errUppercaseMethod = errors.New("method must start with a non-uppercase letter") 25 errInvalidArg = errors.New("couldn't unmarshal an argument. Ensure arguments are valid and properly formatted. See documentation for example calls") 26 ) 27 28 // NewCodec returns a new json codec that will convert the first character of 29 // the method to uppercase 30 func NewCodec() rpc.Codec { 31 return lowercase{json2.NewCodec()} 32 } 33 34 type lowercase struct{ *json2.Codec } 35 36 func (lc lowercase) NewRequest(r *http.Request) rpc.CodecRequest { 37 return &request{lc.Codec.NewRequest(r).(*json2.CodecRequest)} 38 } 39 40 type request struct{ *json2.CodecRequest } 41 42 func (r *request) Method() (string, error) { 43 method, err := r.CodecRequest.Method() 44 methodSections := strings.SplitN(method, ".", 2) 45 if len(methodSections) != 2 || err != nil { 46 return method, err 47 } 48 class, function := methodSections[0], methodSections[1] 49 firstRune, runeLen := utf8.DecodeRuneInString(function) 50 if firstRune == utf8.RuneError { 51 return method, nil 52 } 53 if unicode.IsUpper(firstRune) { 54 return method, errUppercaseMethod 55 } 56 uppercaseRune := string(unicode.ToUpper(firstRune)) 57 return fmt.Sprintf("%s.%s%s", class, uppercaseRune, function[runeLen:]), nil 58 } 59 60 func (r *request) ReadRequest(args interface{}) error { 61 if err := r.CodecRequest.ReadRequest(args); err != nil { 62 return errInvalidArg 63 } 64 return nil 65 }