expect_json/expects/
expect_op_error.rs

1use crate::internals::objects::ArrayObject;
2use crate::internals::objects::ValueObject;
3use crate::internals::objects::ValueTypeObject;
4use crate::internals::ExpectOpMeta;
5use crate::Context;
6use crate::ExpectJsonError;
7use crate::ExpectOp;
8use crate::JsonType;
9use std::error::Error as StdError;
10use thiserror::Error;
11
12pub type ExpectOpResult<V> = Result<V, ExpectOpError>;
13
14#[derive(Debug, Error)]
15pub enum ExpectOpError {
16    // TODO, this error message should include which operations it _can_ be performed on.
17    // The underlying problem might be the server returned different data to what we expected.
18    #[error(
19        "Json expect::{}() at {context}, received wrong type:
20    expected {}
21    received {received}",
22        expected_operation.name,
23        format_expected_operation_types(expected_operation),
24    )]
25    UnsupportedOperation {
26        context: Context<'static>,
27        received: ValueTypeObject,
28        expected_operation: ExpectOpMeta,
29    },
30
31    #[error(
32        "Json object at {context} is missing key for {}:
33    expected field '{expected_key}',
34    but it was not found",
35        expected_operation.name
36    )]
37    ObjectKeyMissingForExpectOp {
38        context: Context<'static>,
39        expected_key: String,
40        expected_operation: ExpectOpMeta,
41    },
42
43    #[error(
44        "Json at {context} has key with value, expecting either key not present or different value.
45    received {received}"
46    )]
47    ObjectKeyValueIsEqual {
48        context: Context<'static>,
49        received: ValueObject,
50        expected_operation: ExpectOpMeta,
51    },
52
53    #[error(
54        "Json {json_type} at {context} contains value was expecting to not be there:
55    expected {json_type} to not contain {expected}, but it was found.
56    received {received}"
57    )]
58    ContainsFound {
59        context: Context<'static>,
60        json_type: JsonType,
61        expected: ValueObject,
62        received: ValueObject,
63    },
64
65    #[error(
66        "Json {json_type} at {context} does not contain expected value:
67    expected {json_type} to contain {expected}, but it was not found.
68    received {received}"
69    )]
70    ContainsNotFound {
71        context: Context<'static>,
72        json_type: JsonType,
73        expected: ValueObject,
74        received: ValueObject,
75    },
76
77    #[error(
78        "Json array at {context} contains duplicate value, expected array to contain all unique values.
79    duplicate value {duplicate}.
80    received full array {received_array}"
81    )]
82    ArrayContainsDuplicate {
83        context: Context<'static>,
84        duplicate: ValueObject,
85        received_array: ArrayObject,
86    },
87
88    #[error(
89        "Json expect::{}() error at {context}:
90    {message},
91    {error}",
92    expected_operation.name,
93    )]
94    UnknownError {
95        #[source]
96        error: Box<dyn StdError>,
97        context: Context<'static>,
98        message: String,
99        expected_operation: ExpectOpMeta,
100    },
101
102    #[error(
103        "Json expect::{}() error at {context}:
104    {message}",
105    expected_operation.name,
106    )]
107    UnknownErrorMessage {
108        context: Context<'static>,
109        message: String,
110        expected_operation: ExpectOpMeta,
111    },
112
113    #[error("{error}")]
114    ExpectJsonError {
115        #[source]
116        error: Box<ExpectJsonError>,
117    },
118}
119
120impl ExpectOpError {
121    pub fn custom<O, S>(context: &Context<'_>, expect_op: &O, message: S) -> Self
122    where
123        O: ExpectOp + ?Sized,
124        S: Into<String>,
125    {
126        Self::UnknownErrorMessage {
127            context: context.to_static(),
128            message: message.into(),
129            expected_operation: ExpectOpMeta::new(expect_op),
130        }
131    }
132
133    pub fn custom_error<O, S, E>(context: &Context<'_>, expect_op: &O, message: S, error: E) -> Self
134    where
135        O: ExpectOp + ?Sized,
136        S: Into<String>,
137        E: StdError + 'static,
138    {
139        Self::UnknownError {
140            context: context.to_static(),
141            message: message.into(),
142            error: Box::new(error),
143            expected_operation: ExpectOpMeta::new(expect_op),
144        }
145    }
146
147    pub fn unsupported_operation_type<O, V>(
148        context: &Context<'_>,
149        expect_op: &O,
150        received: V,
151    ) -> Self
152    where
153        O: ExpectOp + ?Sized,
154        V: Into<ValueTypeObject>,
155    {
156        Self::UnsupportedOperation {
157            context: context.to_static(),
158            received: received.into(),
159            expected_operation: ExpectOpMeta::new(expect_op),
160        }
161    }
162}
163
164impl From<ExpectJsonError> for ExpectOpError {
165    fn from(error: ExpectJsonError) -> Self {
166        Self::ExpectJsonError {
167            error: Box::new(error),
168        }
169    }
170}
171
172fn format_expected_operation_types(expected_operation: &ExpectOpMeta) -> String {
173    let types = expected_operation.types;
174    if types.is_empty() {
175        return "no supported types listed (need to implement ExpectOp::supported_types)"
176            .to_string();
177    }
178
179    types.join(", ")
180}