isle/go/daemon/jsonrpc2/errors.go

82 lines
2.4 KiB
Go

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
}