use std::num::ParseIntError; use serde_json::Value; use thiserror::Error; #[cfg(doc)] use casper_types::{account::AccountHash, CLValue, Key, NamedArg, PublicKey, URef}; use casper_types::{ bytesrepr::Error as BytesreprError, crypto::Error as CryptoError, CLType, KeyFromStrError, URefFromStrError, }; /// Error associated with parsing a JSON arg into a [`NamedArg`]. #[derive(Error, Debug)] #[error( "failed to construct a CLValue of type {cl_type:?} from {json_value} for arg {arg_name}: \ {details}" )] pub struct Error { /// The name of the relevant argument. pub arg_name: String, /// The `CLType` into which the value should be parsed. pub cl_type: CLType, /// The JSON value from which parsing failed. pub json_value: Value, /// Details of the error. pub details: ErrorDetails, } impl Error { pub(super) fn new( arg_name: String, cl_type: CLType, json_value: Value, details: ErrorDetails, ) -> Self { Error { arg_name, cl_type, json_value, details, } } } /// Details of an error associated with parsing a JSON arg into a [`NamedArg`]. #[derive(Error, Debug)] pub enum ErrorDetails { /// bytesrepr error while constructing a [`CLValue`]. #[error("failed bytesrepr encoding: {0}")] Bytesrepr(BytesreprError), /// Cannot convert the given JSON Number to an `i32`. #[error("cannot convert given JSON Number to `i32`")] CannotParseToI32, /// Cannot convert the given JSON Number to an `i64`. #[error("cannot convert given JSON Number to `i64`")] CannotParseToI64, /// Cannot convert the given JSON Number to a `u8`. #[error("cannot convert given JSON Number to `u8`")] CannotParseToU8, /// Cannot convert the given JSON Number to a `u32`. #[error("cannot convert given JSON Number to `u32`")] CannotParseToU32, /// Cannot convert the given JSON Number to a `u64`. #[error("cannot convert given JSON Number to `u64`")] CannotParseToU64, /// Error parsing an integer from a decimal string representation. #[error(transparent)] ParseInt(#[from] ParseIntError), /// Error parsing a big integer from a decimal string representation. #[error(transparent)] ParseBigint(#[from] uint::FromDecStrErr), /// Error parsing a [`Key`] from a formatted string representation. #[error("failed parsing a Key: {0}")] ParseKeyFromString(KeyFromStrError), /// JSON Object representing a [`Key`] must have the structure /// `{"":""}`, but the given one does not have just one /// field. #[error( "invalid number of fields: JSON Object representing a Key must have exactly one field, the \ name of the Key variant mapped to the Key as a formatted string" )] KeyObjectHasInvalidNumberOfFields, /// JSON Object representing a [`Key`] must have the structure /// `{"":""}`, but the given one does not have a String /// value. #[error( "invalid field type: JSON Object representing a Key must have exactly one field, the name \ of the Key variant mapped to the Key as a formatted string" )] KeyObjectHasInvalidFieldType, /// JSON Object representing a [`Key`] must have the structure /// `{"":""}`, but the given one does match any valid /// `Key` variant. #[error( "invalid Key variant: JSON Object representing a Key must have exactly one field, the name \ of the Key variant mapped to the Key as a formatted string" )] KeyObjectHasInvalidVariant, /// Error parsing a [`URef`] from a formatted string representation. #[error("failed parsing a URef: {0}")] ParseURef(URefFromStrError), /// Error parsing a [`PublicKey`] from a formatted string representation. #[error(transparent)] ParsePublicKey(#[from] CryptoError), /// Error parsing a hex string. #[error(transparent)] HexDecode(#[from] base16::DecodeError), /// Number of hex-decoded bytes not as expected. #[error("number of hex-decoded bytes ({actual_length}) not as expected ({expected_length})")] ByteArrayLengthMismatch { /// The expected number of bytes. expected_length: u32, /// The actual number of bytes. actual_length: u32, }, /// JSON Object representing a `Result` must have the structure `{"Ok":}` or /// `{"Err":}`, but the given one does not have just one field. #[error( "invalid number of fields: JSON Object representing a Result must have exactly one field \ named 'Ok' or 'Err'" )] ResultObjectHasInvalidNumberOfFields, /// JSON Object representing a `Result` must have the structure `{"Ok":}` or /// `{"Err":}`, but the given one is neither `"Ok"` nor `"Err"`. #[error( "invalid Result variant: JSON Object representing a Result must have exactly one field \ named 'Ok' or 'Err'" )] ResultObjectHasInvalidVariant, /// `CLType::Map`s can only be represented as JSON Objects if the map's key type is a string or /// number. #[error( "invalid map key type ({0:?}): only maps with key types of string or number can be \ represented as JSON Objects, maps with more complex key types must use a JSON Array" )] MapTypeNotValidAsObject(CLType), /// JSON Array representing a `CLType::Map` must have all entries with the structure /// `{"key":,"value":}`, but the given one has an entry which is not an Object. #[error("invalid entry type: JSON Array representing a Map must have all entries as Objects")] MapArrayHasInvalidEntryType, /// JSON Object representing a map entry must have the structure /// `{"key":,"value":}`, but the given one does not have exactly two fields. #[error( "invalid number of fields: JSON Object representing a Map entry must have exactly two \ fields, named 'key' and 'value'" )] MapEntryObjectHasInvalidNumberOfFields, /// JSON Object representing a map entry must have the structure /// `{"key":,"value":}`, but the given one does not have `"key"`. #[error( "missing key field: JSON Object representing a Map entry must have exactly two fields, \ named 'key' and 'value'" )] MapEntryObjectMissingKeyField, /// JSON Object representing a map entry must have the structure /// `{"key":,"value":}`, but the given one does not have `"value"`. #[error( "missing value field: JSON Object representing a Map entry must have exactly two fields, \ named 'key' and 'value'" )] MapEntryObjectMissingValueField, /// Number of tuple entries not as expected. #[error("number of tuple entries ({actual}) not as expected ({expected})")] TupleEntryCountMismatch { /// The expected number of tuple entries. expected: usize, /// The actual number of tuple entries. actual: usize, }, /// The given `CLType` fundamentally cannot be constructed from the given type of JSON value. #[error("the given CLType cannot be constructed from the given type of JSON value")] IncompatibleType, } impl From for ErrorDetails { fn from(error: KeyFromStrError) -> Self { ErrorDetails::ParseKeyFromString(error) } } impl From for ErrorDetails { fn from(error: URefFromStrError) -> Self { ErrorDetails::ParseURef(error) } } impl From for ErrorDetails { fn from(error: BytesreprError) -> Self { ErrorDetails::Bytesrepr(error) } }