<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package json

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")
)

// NewCodec returns a new json codec that will convert the first character of
// the method to uppercase
func NewCodec() rpc.Codec {
	return lowercase{json2.NewCodec()}
}

type lowercase struct{ *json2.Codec }

func (lc lowercase) NewRequest(r *http.Request) rpc.CodecRequest {
	return &request{lc.Codec.NewRequest(r).(*json2.CodecRequest)}
}

type request struct{ *json2.CodecRequest }

func (r *request) Method() (string, error) {
	method, err := r.CodecRequest.Method()
	methodSections := strings.SplitN(method, ".", 2)
	if len(methodSections) != 2 || err != nil {
		return method, err
	}
	class, function := methodSections[0], methodSections[1]
	firstRune, runeLen := utf8.DecodeRuneInString(function)
	if firstRune == utf8.RuneError {
		return method, nil
	}
	if unicode.IsUpper(firstRune) {
		return method, errUppercaseMethod
	}
	uppercaseRune := string(unicode.ToUpper(firstRune))
	return fmt.Sprintf("%s.%s%s", class, string(uppercaseRune), function[runeLen:]), nil
}<commit_msg>make error message more clear when an argument can't be unmarshaled<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package json

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")
)

// NewCodec returns a new json codec that will convert the first character of
// the method to uppercase
func NewCodec() rpc.Codec {
	return lowercase{json2.NewCodec()}
}

type lowercase struct{ *json2.Codec }

func (lc lowercase) NewRequest(r *http.Request) rpc.CodecRequest {
	return &request{lc.Codec.NewRequest(r).(*json2.CodecRequest)}
}

type request struct{ *json2.CodecRequest }

func (r *request) Method() (string, error) {
	method, err := r.CodecRequest.Method()
	methodSections := strings.SplitN(method, ".", 2)
	if len(methodSections) != 2 || err != nil {
		return method, err
	}
	class, function := methodSections[0], methodSections[1]
	firstRune, runeLen := utf8.DecodeRuneInString(function)
	if firstRune == utf8.RuneError {
		return method, nil
	}
	if unicode.IsUpper(firstRune) {
		return method, errUppercaseMethod
	}
	uppercaseRune := string(unicode.ToUpper(firstRune))
	return fmt.Sprintf("%s.%s%s", class, string(uppercaseRune), function[runeLen:]), nil
}

func (r *request) ReadRequest(args interface{}) error {
	if err := r.CodecRequest.ReadRequest(args); err != nil {
		return errors.New("couldn't unmarshal an argument. Ensure arguments are valid and properly formatted. See documentation for example calls")
	}
	return nil
}
{'fraction_non_alphanumeric': 0.1315963060686016, 'fraction_numerical': 0.014511873350923483, 'mean_word_length': 4.766159695817491, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6395862', 'n_tokens_mistral': 1077, 'n_tokens_neox': 1055, 'n_words': 280}