package jsonrpc2 import ( "bytes" "encoding/json" "fmt" ) const ( // Invalid JSON was received by the server. // An error occurred on the server while parsing the JSON text. errCodeParse = -32700 // The JSON sent is not a valid Request object. errCodeInvalidRequest = -32600 // The method does not exist / is not available. errCodeMethodNotFound = -32601 // Invalid method parameter(s). errCodeInvalidParams = -32602 // Reserved for implementation-defined server-errors. errCodeServerError = -32000 ) // Error implements the error stuct type defined in the spec, as well as the go // error interface and the `Is` method for the errors package. Note that the // `Is` method will check both the type and Code of the given target in order to // check same-ness. type Error struct { // Code is an identifier for the kind of error being returned. All // application-defined error codes should be positive. Code int `json:"code"` Message string `json:"message"` Data any `json:"data,omitempty"` } // NewError returns an error with the given Code and formatted Message. func NewError(code int, msgFmt string, msgArgs ...any) Error { return Error{Code: code, Message: fmt.Sprintf(msgFmt, msgArgs...)} } // NewInvalidParamsError returns an error indicating that the provided // parameters were invalid. // // Parameters are considered invalid if they could never possibly be valid in // the format they were given and always indicate a bug in the caller. For // example a timedate string in the wrong format. // // If a parameter is invalid due to the context it was used in, for example a // wrong password, a specific error code should be used to indicate that to the // caller. func NewInvalidParamsError(msgFmt string, msgArgs ...any) Error { return NewError(errCodeInvalidParams, msgFmt, msgArgs...) } func (e Error) Error() string { buf := new(bytes.Buffer) fmt.Fprintf(buf, "[%d] %s", e.Code, e.Message) if e.Data != nil { fmt.Fprint(buf, "\nExtra data: ") if err := json.NewEncoder(buf).Encode(e.Data); err != nil { panic(fmt.Sprintf("json encoding Error.Data %#v: %v", e.Data, err)) } } return buf.String() } func (e Error) Is(target error) bool { if tErr, ok := target.(Error); ok { return tErr.Code == e.Code } return false } // WithData returns a copy of the Error with the Data file overwritten. func (e Error) WithData(data any) Error { e.Data = data return e }