casper_client/cli/json_args/
error.rs

1use std::num::ParseIntError;
2
3use serde_json::Value;
4use thiserror::Error;
5
6#[cfg(doc)]
7use casper_types::{account::AccountHash, CLValue, Key, NamedArg, PublicKey, URef};
8use casper_types::{
9    bytesrepr::Error as BytesreprError, crypto::Error as CryptoError, CLType, KeyFromStrError,
10    URefFromStrError,
11};
12
13/// Error associated with parsing a JSON arg into a [`NamedArg`].
14#[derive(Error, Debug)]
15#[error(
16    "failed to construct a CLValue of type {cl_type:?} from {json_value} for arg {arg_name}: \
17    {details}"
18)]
19pub struct Error {
20    /// The name of the relevant argument.
21    pub arg_name: String,
22    /// The `CLType` into which the value should be parsed.
23    pub cl_type: CLType,
24    /// The JSON value from which parsing failed.
25    pub json_value: Value,
26    /// Details of the error.
27    pub details: ErrorDetails,
28}
29
30impl Error {
31    pub(super) fn new(
32        arg_name: String,
33        cl_type: CLType,
34        json_value: Value,
35        details: ErrorDetails,
36    ) -> Self {
37        Error {
38            arg_name,
39            cl_type,
40            json_value,
41            details,
42        }
43    }
44}
45
46/// Details of an error associated with parsing a JSON arg into a [`NamedArg`].
47#[derive(Error, Debug)]
48pub enum ErrorDetails {
49    /// bytesrepr error while constructing a [`CLValue`].
50    #[error("failed bytesrepr encoding: {0}")]
51    Bytesrepr(BytesreprError),
52
53    /// Cannot convert the given JSON Number to an `i32`.
54    #[error("cannot convert given JSON Number to `i32`")]
55    CannotParseToI32,
56
57    /// Cannot convert the given JSON Number to an `i64`.
58    #[error("cannot convert given JSON Number to `i64`")]
59    CannotParseToI64,
60
61    /// Cannot convert the given JSON Number to a `u8`.
62    #[error("cannot convert given JSON Number to `u8`")]
63    CannotParseToU8,
64
65    /// Cannot convert the given JSON Number to a `u32`.
66    #[error("cannot convert given JSON Number to `u32`")]
67    CannotParseToU32,
68
69    /// Cannot convert the given JSON Number to a `u64`.
70    #[error("cannot convert given JSON Number to `u64`")]
71    CannotParseToU64,
72
73    /// Error parsing an integer from a decimal string representation.
74    #[error(transparent)]
75    ParseInt(#[from] ParseIntError),
76
77    /// Error parsing a big integer from a decimal string representation.
78    #[error(transparent)]
79    ParseBigint(#[from] uint::FromDecStrErr),
80
81    /// Error parsing a [`Key`] from a formatted string representation.
82    #[error("failed parsing a Key: {0}")]
83    ParseKeyFromString(KeyFromStrError),
84
85    /// JSON Object representing a [`Key`] must have the structure
86    /// `{"<KEY VARIANT>":"<KEY AS FORMATTED STRING>"}`, but the given one does not have just one
87    /// field.
88    #[error(
89        "invalid number of fields: JSON Object representing a Key must have exactly one field, the \
90        name of the Key variant mapped to the Key as a formatted string"
91    )]
92    KeyObjectHasInvalidNumberOfFields,
93
94    /// JSON Object representing a [`Key`] must have the structure
95    /// `{"<KEY VARIANT>":"<KEY AS FORMATTED STRING>"}`, but the given one does not have a String
96    /// value.
97    #[error(
98        "invalid field type: JSON Object representing a Key must have exactly one field, the name \
99        of the Key variant mapped to the Key as a formatted string"
100    )]
101    KeyObjectHasInvalidFieldType,
102
103    /// JSON Object representing a [`Key`] must have the structure
104    /// `{"<KEY VARIANT>":"<KEY AS FORMATTED STRING>"}`, but the given one does match any valid
105    /// `Key` variant.
106    #[error(
107        "invalid Key variant: JSON Object representing a Key must have exactly one field, the name \
108        of the Key variant mapped to the Key as a formatted string"
109    )]
110    KeyObjectHasInvalidVariant,
111
112    /// Error parsing a [`URef`] from a formatted string representation.
113    #[error("failed parsing a URef: {0}")]
114    ParseURef(URefFromStrError),
115
116    /// Error parsing a [`PublicKey`] from a formatted string representation.
117    #[error(transparent)]
118    ParsePublicKey(#[from] CryptoError),
119
120    /// Error parsing a hex string.
121    #[error(transparent)]
122    HexDecode(#[from] base16::DecodeError),
123
124    /// Number of hex-decoded bytes not as expected.
125    #[error("number of hex-decoded bytes ({actual_length}) not as expected ({expected_length})")]
126    ByteArrayLengthMismatch {
127        /// The expected number of bytes.
128        expected_length: u32,
129        /// The actual number of bytes.
130        actual_length: u32,
131    },
132
133    /// JSON Object representing a `Result` must have the structure `{"Ok":<VALUE>}` or
134    /// `{"Err":<VALUE>}`, but the given one does not have just one field.
135    #[error(
136        "invalid number of fields: JSON Object representing a Result must have exactly one field \
137        named 'Ok' or 'Err'"
138    )]
139    ResultObjectHasInvalidNumberOfFields,
140
141    /// JSON Object representing a `Result` must have the structure `{"Ok":<VALUE>}` or
142    /// `{"Err":<VALUE>}`, but the given one is neither `"Ok"` nor `"Err"`.
143    #[error(
144        "invalid Result variant: JSON Object representing a Result must have exactly one field \
145        named 'Ok' or 'Err'"
146    )]
147    ResultObjectHasInvalidVariant,
148
149    /// `CLType::Map`s can only be represented as JSON Objects if the map's key type is a string or
150    /// number.
151    #[error(
152        "invalid map key type ({0:?}): only maps with key types of string or number can be \
153        represented as JSON Objects, maps with more complex key types must use a JSON Array"
154    )]
155    MapTypeNotValidAsObject(CLType),
156
157    /// JSON Array representing a `CLType::Map` must have all entries with the structure
158    /// `{"key":<VALUE>,"value":<VALUE>}`, but the given one has an entry which is not an Object.
159    #[error("invalid entry type: JSON Array representing a Map must have all entries as Objects")]
160    MapArrayHasInvalidEntryType,
161
162    /// JSON Object representing a map entry must have the structure
163    /// `{"key":<VALUE>,"value":<VALUE>}`, but the given one does not have exactly two fields.
164    #[error(
165        "invalid number of fields: JSON Object representing a Map entry must have exactly two \
166        fields, named 'key' and 'value'"
167    )]
168    MapEntryObjectHasInvalidNumberOfFields,
169
170    /// JSON Object representing a map entry must have the structure
171    /// `{"key":<VALUE>,"value":<VALUE>}`, but the given one does not have `"key"`.
172    #[error(
173        "missing key field: JSON Object representing a Map entry must have exactly two fields, \
174        named 'key' and 'value'"
175    )]
176    MapEntryObjectMissingKeyField,
177
178    /// JSON Object representing a map entry must have the structure
179    /// `{"key":<VALUE>,"value":<VALUE>}`, but the given one does not have `"value"`.
180    #[error(
181        "missing value field: JSON Object representing a Map entry must have exactly two fields, \
182        named 'key' and 'value'"
183    )]
184    MapEntryObjectMissingValueField,
185
186    /// Number of tuple entries not as expected.
187    #[error("number of tuple entries ({actual}) not as expected ({expected})")]
188    TupleEntryCountMismatch {
189        /// The expected number of tuple entries.
190        expected: usize,
191        /// The actual number of tuple entries.
192        actual: usize,
193    },
194
195    /// The given `CLType` fundamentally cannot be constructed from the given type of JSON value.
196    #[error("the given CLType cannot be constructed from the given type of JSON value")]
197    IncompatibleType,
198}
199
200impl From<KeyFromStrError> for ErrorDetails {
201    fn from(error: KeyFromStrError) -> Self {
202        ErrorDetails::ParseKeyFromString(error)
203    }
204}
205
206impl From<URefFromStrError> for ErrorDetails {
207    fn from(error: URefFromStrError) -> Self {
208        ErrorDetails::ParseURef(error)
209    }
210}
211
212impl From<BytesreprError> for ErrorDetails {
213    fn from(error: BytesreprError) -> Self {
214        ErrorDetails::Bytesrepr(error)
215    }
216}