asserting/option/
mod.rs

1//! Implementation of assertions for `Option` values.
2
3use crate::assertions::{
4    AssertBorrowedOptionValue, AssertHasValue, AssertOption, AssertOptionValue,
5};
6use crate::colored::{mark_missing, mark_unexpected};
7use crate::expectations::{has_value, is_none, is_some, HasValue, IsNone, IsSome};
8use crate::spec::{
9    DiffFormat, Expectation, Expression, FailingStrategy, Invertible, Spec, Unknown,
10};
11use crate::std::fmt::Debug;
12use crate::std::{format, string::String};
13
14impl<S, R> AssertOption for Spec<'_, Option<S>, R>
15where
16    S: Debug,
17    R: FailingStrategy,
18{
19    fn is_some(self) -> Self {
20        self.expecting(is_some())
21    }
22
23    fn is_none(self) -> Self {
24        self.expecting(is_none())
25    }
26}
27
28impl<S, R> AssertOption for Spec<'_, &Option<S>, R>
29where
30    S: Debug,
31    R: FailingStrategy,
32{
33    fn is_some(self) -> Self {
34        self.expecting(is_some())
35    }
36
37    fn is_none(self) -> Self {
38        self.expecting(is_none())
39    }
40}
41
42impl<'a, T, R> AssertOptionValue<'a, T, R> for Spec<'a, Option<T>, R>
43where
44    R: FailingStrategy,
45{
46    fn some(self) -> Spec<'a, T, R> {
47        self.mapping(|subject| match subject {
48            None => {
49                panic!("expected the subject to be `Some(_)`, but was `None`")
50            },
51            Some(value) => value,
52        })
53    }
54}
55
56impl<'a, T, R> AssertBorrowedOptionValue<'a, T, R> for Spec<'a, &'a Option<T>, R>
57where
58    R: FailingStrategy,
59{
60    fn some(self) -> Spec<'a, &'a T, R> {
61        self.mapping(|subject| match subject {
62            None => {
63                panic!("expected the subject to be `Some(_)`, but was `None`")
64            },
65            Some(value) => value,
66        })
67    }
68}
69
70impl<S, E, R> AssertHasValue<E> for Spec<'_, Option<S>, R>
71where
72    S: PartialEq<E> + Debug,
73    E: Debug,
74    R: FailingStrategy,
75{
76    fn has_value(self, expected: E) -> Self {
77        self.expecting(has_value(expected))
78    }
79}
80
81impl<S, E, R> AssertHasValue<E> for Spec<'_, &Option<S>, R>
82where
83    S: PartialEq<E> + Debug,
84    E: Debug,
85    R: FailingStrategy,
86{
87    fn has_value(self, expected: E) -> Self {
88        self.expecting(has_value(expected))
89    }
90}
91
92impl<T> Expectation<Option<T>> for IsSome
93where
94    T: Debug,
95{
96    fn test(&mut self, subject: &Option<T>) -> bool {
97        subject.is_some()
98    }
99
100    fn message(
101        &self,
102        expression: &Expression<'_>,
103        actual: &Option<T>,
104        _inverted: bool,
105        format: &DiffFormat,
106    ) -> String {
107        let expected = Some(Unknown);
108        let marked_actual = mark_unexpected(actual, format);
109        let marked_expected = mark_missing(&expected, format);
110        format!(
111            "expected {expression} to be {expected:?}\n   but was: {marked_actual}\n  expected: {marked_expected}"
112        )
113    }
114}
115
116impl<T> Expectation<&Option<T>> for IsSome
117where
118    T: Debug,
119{
120    fn test(&mut self, subject: &&Option<T>) -> bool {
121        <Self as Expectation<Option<T>>>::test(self, subject)
122    }
123
124    fn message(
125        &self,
126        expression: &Expression<'_>,
127        actual: &&Option<T>,
128        inverted: bool,
129        format: &DiffFormat,
130    ) -> String {
131        <Self as Expectation<Option<T>>>::message(self, expression, actual, inverted, format)
132    }
133}
134
135impl<T> Expectation<Option<T>> for IsNone
136where
137    T: Debug,
138{
139    fn test(&mut self, subject: &Option<T>) -> bool {
140        subject.is_none()
141    }
142
143    fn message(
144        &self,
145        expression: &Expression<'_>,
146        actual: &Option<T>,
147        _inverted: bool,
148        format: &DiffFormat,
149    ) -> String {
150        let expected = None::<Unknown>;
151        let marked_actual = mark_unexpected(actual, format);
152        let marked_expected = mark_missing(&expected, format);
153        format!(
154            "expected {expression} to be {expected:?}\n   but was: {marked_actual}\n  expected: {marked_expected}"
155        )
156    }
157}
158
159impl<T> Expectation<&Option<T>> for IsNone
160where
161    T: Debug,
162{
163    fn test(&mut self, subject: &&Option<T>) -> bool {
164        <Self as Expectation<Option<T>>>::test(self, subject)
165    }
166
167    fn message(
168        &self,
169        expression: &Expression<'_>,
170        actual: &&Option<T>,
171        inverted: bool,
172        format: &DiffFormat,
173    ) -> String {
174        <Self as Expectation<Option<T>>>::message(self, expression, actual, inverted, format)
175    }
176}
177
178impl<T, E> Expectation<Option<T>> for HasValue<E>
179where
180    T: PartialEq<E> + Debug,
181    E: Debug,
182{
183    fn test(&mut self, subject: &Option<T>) -> bool {
184        subject
185            .as_ref()
186            .is_some_and(|value| value == &self.expected)
187    }
188
189    fn message(
190        &self,
191        expression: &Expression<'_>,
192        actual: &Option<T>,
193        inverted: bool,
194        format: &DiffFormat,
195    ) -> String {
196        let not = if inverted { "not " } else { "" };
197        let expected = &self.expected;
198        let marked_actual = mark_unexpected(actual, format);
199        let marked_expected = mark_missing(&Some(expected), format);
200        format!("expected {expression} to be some {not}containing {expected:?}\n   but was: {marked_actual}\n  expected: {not}{marked_expected}")
201    }
202}
203
204impl<E> Invertible for HasValue<E> {}
205
206impl<T, E> Expectation<&Option<T>> for HasValue<E>
207where
208    T: PartialEq<E> + Debug,
209    E: Debug,
210{
211    fn test(&mut self, subject: &&Option<T>) -> bool {
212        <Self as Expectation<Option<T>>>::test(self, subject)
213    }
214
215    fn message(
216        &self,
217        expression: &Expression<'_>,
218        actual: &&Option<T>,
219        inverted: bool,
220        format: &DiffFormat,
221    ) -> String {
222        <Self as Expectation<Option<T>>>::message(self, expression, actual, inverted, format)
223    }
224}
225
226#[cfg(test)]
227mod tests;