Skip to main content

asserting/derived_spec/
mod.rs

1//! Defines the [`DerivedSpec`], which keeps track of the original subject while doing assertions
2//! on a derived subject.
3
4use crate::assertions::{
5    AssertBoolean, AssertChar, AssertDebugString, AssertDecimalNumber, AssertDisplayString,
6    AssertElements, AssertEmptiness, AssertEquality, AssertErrorHasSource, AssertHasCharCount,
7    AssertHasDebugString, AssertHasDisplayString, AssertHasError, AssertHasErrorMessage,
8    AssertHasLength, AssertHasValue, AssertInRange, AssertInfinity, AssertIteratorContains,
9    AssertIteratorContainsInAnyOrder, AssertIteratorContainsInOrder, AssertMapContainsKey,
10    AssertMapContainsValue, AssertNotANumber, AssertNumericIdentity, AssertOption,
11    AssertOptionValue, AssertOrder, AssertOrderedElements, AssertOrderedElementsRef, AssertResult,
12    AssertResultValue, AssertSameAs, AssertSignum, AssertStringContainsAnyOf, AssertStringPattern,
13};
14use crate::expectations::{
15    error_has_source, error_has_source_message, has_at_least_char_count, has_at_least_length,
16    has_at_least_number_of_elements, has_at_most_char_count, has_at_most_length, has_char_count,
17    has_char_count_greater_than, has_char_count_in_range, has_char_count_less_than,
18    has_debug_string, has_display_string, has_error, has_length, has_length_greater_than,
19    has_length_in_range, has_length_less_than, has_precision_of, has_scale_of, has_value,
20    is_a_number, is_after, is_alphabetic, is_alphanumeric, is_ascii, is_at_least, is_at_most,
21    is_before, is_between, is_control_char, is_digit, is_empty, is_equal_to, is_err, is_false,
22    is_finite, is_greater_than, is_in_range, is_infinite, is_integer, is_less_than, is_lower_case,
23    is_negative, is_none, is_ok, is_one, is_positive, is_same_as, is_some, is_true, is_upper_case,
24    is_whitespace, is_zero, iterator_contains, iterator_contains_all_in_order,
25    iterator_contains_all_of, iterator_contains_any_of, iterator_contains_exactly,
26    iterator_contains_exactly_in_any_order, iterator_contains_only, iterator_contains_only_once,
27    iterator_contains_sequence, iterator_ends_with, iterator_starts_with,
28    map_contains_exactly_keys, map_contains_key, map_contains_keys, map_contains_value,
29    map_contains_values, map_does_not_contain_keys, map_does_not_contain_values, not, satisfies,
30    string_contains, string_contains_any_of, string_ends_with, string_starts_with,
31};
32use crate::properties::{
33    AdditiveIdentityProperty, CharCountProperty, DecimalProperties, DefinedOrderProperty,
34    InfinityProperty, IsEmptyProperty, IsNanProperty, LengthProperty, MapProperties,
35    MultiplicativeIdentityProperty, SignumProperty,
36};
37use crate::spec::{
38    And, AssertFailure, CollectFailures, DiffFormat, DoFail, Expectation, Expecting, Expression,
39    FailingStrategy, GetFailures, GetLocation, Location, PanicOnFail, Satisfies, SoftPanic, Spec,
40};
41use crate::std::borrow::{Cow, ToOwned};
42use crate::std::error::Error;
43use crate::std::fmt::{Debug, Display};
44use crate::std::format;
45use crate::std::ops::RangeBounds;
46use crate::std::slice;
47use crate::std::string::{String, ToString};
48use crate::std::vec::Vec;
49use hashbrown::HashSet;
50
51/// A `DerivedSpec` does assertions on a derived subject while keeping track
52/// of the original subject.
53///
54/// It has similar functionality to a [`Spec`], but additionally holds the
55/// original subject. Calling the `and` method switches the subject back to the
56/// original subject.
57///
58/// The derived subject can have its own name and diff format in failure
59/// reports.
60///
61/// [`Spec`]: Spec
62pub struct DerivedSpec<'a, O, S> {
63    original: O,
64    subject: S,
65    expression: Expression<'a>,
66    diff_format: DiffFormat,
67}
68
69impl<O, S> DerivedSpec<'_, O, S> {
70    /// Returns the expression (or subject name) if one has been set.
71    pub fn expression(&self) -> &Expression<'_> {
72        &self.expression
73    }
74
75    /// Returns the diff format used with this assertion.
76    pub const fn diff_format(&self) -> &DiffFormat {
77        &self.diff_format
78    }
79}
80
81impl<'a, O, S> DerivedSpec<'a, O, S> {
82    #[must_use = "a derived spec does nothing unless an assertion method is called"]
83    pub(crate) fn new(
84        original: O,
85        derived_subject: S,
86        expression: Expression<'a>,
87        diff_format: DiffFormat,
88    ) -> Self {
89        Self {
90            original,
91            subject: derived_subject,
92            expression,
93            diff_format,
94        }
95    }
96
97    /// Sets the subject name or expression for this assertion.
98    #[must_use = "a derived spec does nothing unless an assertion method is called"]
99    pub fn named(mut self, subject_name: impl Into<Cow<'a, str>>) -> Self {
100        self.expression = Expression(subject_name.into());
101        self
102    }
103
104    /// Sets the diff format used to highlight differences between the actual
105    /// value and the expected value.
106    ///
107    /// Note: This method must be called before an assertion method is called to
108    /// affect the failure message of the assertion as failure messages are
109    /// formatted immediately when an assertion is executed.
110    #[must_use = "a spec does nothing unless an assertion method is called"]
111    pub const fn with_diff_format(mut self, diff_format: DiffFormat) -> Self {
112        self.diff_format = diff_format;
113        self
114    }
115}
116
117impl<'a, O, S> GetLocation<'a> for DerivedSpec<'a, O, S>
118where
119    O: GetLocation<'a>,
120{
121    fn location(&self) -> Option<Location<'a>> {
122        self.original.location()
123    }
124}
125
126impl<O, S> GetFailures for DerivedSpec<'_, O, S>
127where
128    O: GetFailures,
129{
130    fn has_failures(&self) -> bool {
131        self.original.has_failures()
132    }
133
134    fn failures(&self) -> Vec<AssertFailure> {
135        self.original.failures()
136    }
137
138    fn display_failures(&self) -> Vec<String> {
139        self.original.display_failures()
140    }
141}
142
143impl<O, S> DoFail for DerivedSpec<'_, O, S>
144where
145    O: DoFail,
146{
147    fn do_fail_with(&mut self, failures: impl IntoIterator<Item = AssertFailure>) {
148        self.original.do_fail_with(failures);
149    }
150
151    fn do_fail_with_message(&mut self, message: impl Into<String>) {
152        self.original.do_fail_with_message(message);
153    }
154}
155
156impl<O, S> SoftPanic for DerivedSpec<'_, O, S>
157where
158    O: SoftPanic,
159{
160    fn soft_panic(&self) {
161        self.original.soft_panic();
162    }
163}
164
165impl<O, S> And for DerivedSpec<'_, O, S> {
166    type Output = O;
167
168    fn and(self) -> Self::Output {
169        self.original
170    }
171}
172
173impl<'a, O, S> DerivedSpec<'a, O, S> {
174    /// Extracts a property from the current subject.
175    ///
176    /// The extracting closure gets a reference to the current subject as an
177    /// argument and should return a reference to the extracted property. The
178    /// given property name is used in failure reports for referencing the
179    /// property for which an assertion fails.
180    ///
181    /// Use this method if you want to extract multiple properties from the
182    /// same subject for individual assertions on each of these properties.
183    /// To extract another property from the previous subject, call the `and`
184    /// method to switch back to the previous subject before calling
185    /// `extracting_ref` for the other property.
186    ///
187    /// The expression for failure reports is built from the expression of the
188    /// original subject, a dot as a separator, and the given property name.
189    /// The resulting expression is equal to
190    /// `format!("{original_expression}.{property_name}")`.
191    ///
192    /// If you do not like the default built expression, it can be overwritten
193    /// by calling the `named` method after the call to the `extract` method.
194    ///
195    /// # Arguments
196    ///
197    /// * `property_name` - A name describing the extracted property used for
198    ///   referencing that property in failure reports.
199    /// * `extract` - A closure that returns a reference to the property to be
200    ///   extracted.
201    ///
202    /// # Examples
203    ///
204    /// ```
205    /// use asserting::prelude::*;
206    ///
207    /// #[derive(Debug, Clone)]
208    /// struct Item {
209    ///     name: String,
210    ///     price: f32,
211    ///     quantity: u32,
212    /// }
213    ///
214    /// struct Order {
215    ///     id: String,
216    ///     items: Vec<Item>,
217    /// }
218    ///
219    /// let my_order = Order {
220    ///     id: "O261234".into(),
221    ///     items: vec![
222    ///         Item {
223    ///             name: "Apple".into(),
224    ///             price: 0.99,
225    ///             quantity: 6,
226    ///         },
227    ///         Item {
228    ///             name: "Orange".into(),
229    ///             price: 1.99,
230    ///             quantity: 4,
231    ///         },
232    ///     ],
233    /// };
234    ///
235    /// assert_that!(my_order)
236    ///     .extracting_ref("items", |o| &o.items)
237    ///     .extracting_ref("[0].name", |i| &i[0].name)
238    ///     .is_equal_to("Apple")
239    ///     .and()
240    ///     .extracting_ref("[1].name", |i| &i[1].name)
241    ///     .is_equal_to("Orange")
242    ///     .and()
243    ///     .extracting_ref("[1].quantity", |i| &i[1].quantity)
244    ///     .is_equal_to(4)
245    ///     .and()  // switches back to `my_order.items`
246    ///     .and()  // second call to `and()` switches back to `my_order`
247    ///     .extracting_ref("id", |o| &o.id)
248    ///     .is_equal_to("O261234");
249    /// ```
250    ///
251    /// Hint: To avoid having to call the `and()` method two or more times, it
252    /// is recommended to first extract all properties from the higher level
253    /// subject and then extract fields from deeper down in the hierarchy.
254    ///
255    /// ```
256    /// # use asserting::prelude::*;
257    /// #
258    /// # #[derive(Debug, Clone)]
259    /// # struct Item {
260    /// #     name: String,
261    /// #     price: f32,
262    /// #     quantity: u32,
263    /// # }
264    /// #
265    /// # struct Order {
266    /// #     id: String,
267    /// #     items: Vec<Item>,
268    /// # }
269    /// #
270    /// # let my_order = Order {
271    /// #     id: "O261234".into(),
272    /// #     items: vec![
273    /// #         Item {
274    /// #             name: "Apple".into(),
275    /// #             price: 0.99,
276    /// #             quantity: 6,
277    /// #         },
278    /// #         Item {
279    /// #             name: "Orange".into(),
280    /// #             price: 1.99,
281    /// #             quantity: 4,
282    /// #         },
283    /// #     ],
284    /// # };
285    /// #
286    /// assert_that!(my_order)
287    ///     .extracting_ref("id", |o| &o.id)
288    ///     .is_equal_to("O261234")
289    ///     .and()
290    ///     .extracting_ref("items", |o| &o.items)
291    ///     .extracting_ref("[0].name", |i| &i[0].name)
292    ///     .is_equal_to("Apple")
293    ///     .and()
294    ///     .extracting_ref("[1].name", |i| &i[1].name)
295    ///     .is_equal_to("Orange")
296    ///     .and()
297    ///     .extracting_ref("[1].quantity", |i| &i[1].quantity)
298    ///     .is_equal_to(4);
299    /// ```
300    #[must_use = "a derived spec does nothing unless an assertion method is called"]
301    pub fn extracting_ref<F, B, U>(
302        self,
303        property_name: impl Into<Cow<'a, str>>,
304        extract: F,
305    ) -> DerivedSpec<'a, Self, U>
306    where
307        F: FnOnce(&S) -> &B,
308        B: ToOwned<Owned = U> + ?Sized,
309    {
310        let derived_subject = extract(&self.subject).to_owned();
311        let orig_subject_name = &self.expression;
312        let property_name = property_name.into();
313        let expression = Expression(format!("{orig_subject_name}.{property_name}").into());
314        let diff_format = self.diff_format.clone();
315        DerivedSpec {
316            original: self,
317            subject: derived_subject,
318            expression,
319            diff_format,
320        }
321    }
322
323    /// Maps the current subject to some other value.
324    ///
325    /// It takes a closure that maps the current subject to a new subject and
326    /// returns a new `DerivedSpec` with the value returned by the closure as
327    /// the new subject. The new subject may have a different type than the
328    /// original subject. All other data like description, location, and diff
329    /// format are taken over from this `DerivedSpec` into the returned
330    /// `DerivedSpec`.
331    ///
332    /// This method is useful when having a custom type, and one specific
333    /// property of this type shall be asserted only. If you want to assert
334    /// multiple properties of the same subject, use the [`extracting_ref`]
335    /// method instead.
336    ///
337    /// This method is similar to the [`mapping`] method. In contrast to
338    /// [`mapping`], this method does not copy the subject's name
339    /// (or expression) but resets it to the default "subject". The idea is
340    /// that the "extracted" property is most likely a different subject than
341    /// the original one.
342    ///
343    /// The expression for failure reports is built from the expression of the
344    /// original subject, a dot as a separator, and the given property name.
345    /// The resulting expression is equal to
346    /// `format!("{original_expression}.{property_name}")`.
347    ///
348    /// If you do not like the default built expression, it can be overwritten
349    /// by calling the `named` method after the call to the `extract` method.
350    ///
351    /// This method does not memorize the current subject. Calling `and` on the
352    /// extracted property switches back to the original subject of this
353    /// `DerivedSpec`. The current subject is omitted. So, `and` always switches
354    /// back to the subject before the last `extracting_ref` call.
355    ///
356    /// # Arguments
357    ///
358    /// * `property_name` - A name describing the extracted property used for
359    ///   referencing this property in failure reports.
360    /// * `extract` - A closure that returns the property to be extracted.
361    ///
362    /// # Example
363    ///
364    /// ```
365    /// use asserting::prelude::*;
366    ///
367    /// #[derive(Debug, Clone)]
368    /// struct Item {
369    ///     name: String,
370    ///     price: f32,
371    ///     quantity: u32,
372    /// }
373    ///
374    /// struct Order {
375    ///     id: String,
376    ///     items: Vec<Item>,
377    /// }
378    ///
379    /// let my_order = Order {
380    ///     id: "O261234".into(),
381    ///     items: vec![
382    ///         Item {
383    ///             name: "Apple".into(),
384    ///             price: 0.99,
385    ///             quantity: 6,
386    ///         },
387    ///         Item {
388    ///             name: "Orange".into(),
389    ///             price: 1.99,
390    ///             quantity: 4,
391    ///         },
392    ///     ],
393    /// };
394    ///
395    /// assert_that!(my_order)
396    ///     .extracting_ref("items", |o| &o.items)
397    ///     .extracting("name", |i| i[0].name.clone())
398    ///     .is_equal_to("Apple")
399    ///     .and()  // switches back to `my_order` not `my_order.items`
400    ///     .extracting("id", |o| o.id)
401    ///     .is_equal_to("O261234");
402    /// ```
403    ///
404    /// [`extracting_ref`]: Self::extracting_ref
405    /// [`mapping`]: Self::mapping
406    #[must_use = "a derived spec does nothing unless an assertion method is called"]
407    pub fn extracting<F, U>(
408        self,
409        property_name: impl Into<Cow<'a, str>>,
410        extract: F,
411    ) -> DerivedSpec<'a, O, U>
412    where
413        F: FnOnce(S) -> U,
414    {
415        let derived_subject = extract(self.subject);
416        let orig_subject_name = &self.expression;
417        let property_name = property_name.into();
418        let expression = Expression(format!("{orig_subject_name}.{property_name}").into());
419        let diff_format = self.diff_format.clone();
420        DerivedSpec {
421            original: self.original,
422            subject: derived_subject,
423            expression,
424            diff_format,
425        }
426    }
427
428    /// Maps the current subject to some other value.
429    ///
430    /// It takes a closure that maps the current subject to a new subject and
431    /// returns a new `DerivedSpec` with the value returned by the closure as
432    /// the new subject. The new subject may have a different type than the
433    /// original subject. All other data like expression, description, and
434    /// location are taken over from this `DerivedSpec` into the returned
435    /// `DerivedSpec`.
436    ///
437    /// This method is useful if some type does not implement a trait required
438    /// for an assertion.
439    ///
440    /// `DerivedSpec` also provides the [`extracting()`](DerivedSpec::extracting)
441    /// method, which is similar to this method. In contrast to this method,
442    /// [`extracting()`](DerivedSpec::extracting) does not copy the subject's
443    /// name (or expression) but builds a new expression from the expression of
444    /// the original subject and the given property name.
445    ///
446    /// # Example
447    ///
448    /// ```
449    /// use asserting::prelude::*;
450    ///
451    /// #[derive(Clone, Copy)]
452    /// struct Point {
453    ///     x: i64,
454    ///     y: i64,
455    /// }
456    ///
457    /// struct Line {
458    ///     a: Point,
459    ///     b: Point,
460    /// }
461    ///
462    /// let line = Line {
463    ///     a: Point { x: 12, y: -64 },
464    ///     b: Point { x: -28, y: 17 },
465    /// };
466    ///
467    /// assert_that!(line)
468    ///     .extracting_ref("a", |l| &l.a)
469    ///     .mapping(|p| (p.x, p.y))
470    ///     .is_equal_to((12, -64))
471    ///     .and()
472    ///     .extracting_ref("b", |l| &l.b)
473    ///     .mapping(|p| (p.x, p.y))
474    ///     .is_equal_to((-28, 17));
475    /// ```
476    ///
477    /// The custom type `Point` does not implement the `PartialEq` trait nor
478    /// the `Debug` trait, which are both required for an `is_equal_to`
479    /// assertion. So we map the subject of the type `Point` to a tuple of its
480    /// fields.
481    #[must_use = "a derived spec does nothing unless an assertion method is called"]
482    pub fn mapping<F, U>(self, map: F) -> DerivedSpec<'a, O, U>
483    where
484        F: FnOnce(S) -> U,
485    {
486        let mapped = map(self.subject);
487        DerivedSpec {
488            original: self.original,
489            subject: mapped,
490            expression: self.expression,
491            diff_format: self.diff_format,
492        }
493    }
494}
495
496impl<'a, O, I> DerivedSpec<'a, O, I>
497where
498    I: IntoIterator,
499{
500    pub(crate) fn extracting_ref_iter<F, U>(
501        self,
502        property_name: impl Into<Cow<'a, str>>,
503        extract: F,
504    ) -> DerivedSpec<'a, DerivedSpec<'a, O, Vec<<I as IntoIterator>::Item>>, Vec<U>>
505    where
506        for<'b> F: Fn(slice::Iter<'b, <I as IntoIterator>::Item>) -> Vec<U>,
507    {
508        let property_name = Expression(property_name.into());
509        let diff_format = self.diff_format.clone();
510        let orig_spec = self.mapping(Vec::from_iter);
511        let new_subject = extract(orig_spec.subject.iter());
512        DerivedSpec {
513            original: orig_spec,
514            subject: new_subject,
515            expression: property_name,
516            diff_format,
517        }
518    }
519}
520
521impl<O, S> Satisfies<S> for DerivedSpec<'_, O, S>
522where
523    O: DoFail,
524{
525    fn satisfies<P>(self, predicate: P) -> Self
526    where
527        P: Fn(&S) -> bool,
528    {
529        self.expecting(satisfies(predicate))
530    }
531
532    fn satisfies_with_message<P>(self, message: impl Into<String>, predicate: P) -> Self
533    where
534        P: Fn(&S) -> bool,
535    {
536        self.expecting(satisfies(predicate).with_message(message))
537    }
538}
539
540impl<O, S> Expecting<S> for DerivedSpec<'_, O, S>
541where
542    O: DoFail,
543{
544    fn expecting(mut self, mut expectation: impl Expectation<S>) -> Self {
545        if !expectation.test(&self.subject) {
546            let message =
547                expectation.message(&self.expression, &self.subject, false, &self.diff_format);
548            self.do_fail_with_message(message);
549        }
550        self
551    }
552}
553
554impl<O, S, E> AssertEquality<E> for DerivedSpec<'_, O, S>
555where
556    S: PartialEq<E> + Debug,
557    E: Debug,
558    O: DoFail,
559{
560    fn is_equal_to(self, expected: E) -> Self {
561        self.expecting(is_equal_to(expected))
562    }
563
564    fn is_not_equal_to(self, expected: E) -> Self {
565        self.expecting(not(is_equal_to(expected)))
566    }
567}
568
569impl<O, S> AssertSameAs<S> for DerivedSpec<'_, O, S>
570where
571    S: PartialEq + Debug,
572    O: DoFail,
573{
574    fn is_same_as(self, expected: S) -> Self {
575        self.expecting(is_same_as(expected))
576    }
577
578    fn is_not_same_as(self, expected: S) -> Self {
579        self.expecting(not(is_same_as(expected)))
580    }
581}
582
583#[cfg(feature = "float-cmp")]
584mod float_cmp {
585    use super::DerivedSpec;
586    use crate::assertions::{AssertIsCloseToWithDefaultMargin, AssertIsCloseToWithinMargin};
587    use crate::expectations::{is_close_to, not};
588    use crate::spec::{DoFail, Expecting};
589    use float_cmp::{F32Margin, F64Margin};
590
591    impl<O> AssertIsCloseToWithinMargin<f32, F32Margin> for DerivedSpec<'_, O, f32>
592    where
593        O: DoFail,
594    {
595        fn is_close_to_with_margin(self, expected: f32, margin: impl Into<F32Margin>) -> Self {
596            self.expecting(is_close_to(expected).within_margin(margin))
597        }
598
599        fn is_not_close_to_with_margin(self, expected: f32, margin: impl Into<F32Margin>) -> Self {
600            self.expecting(not(is_close_to(expected).within_margin(margin)))
601        }
602    }
603
604    impl<O> AssertIsCloseToWithDefaultMargin<f32> for DerivedSpec<'_, O, f32>
605    where
606        O: DoFail,
607    {
608        fn is_close_to(self, expected: f32) -> Self {
609            self.expecting(is_close_to(expected).within_margin((4. * f32::EPSILON, 4)))
610        }
611
612        fn is_not_close_to(self, expected: f32) -> Self {
613            self.expecting(not(
614                is_close_to(expected).within_margin((4. * f32::EPSILON, 4))
615            ))
616        }
617    }
618
619    impl<O> AssertIsCloseToWithinMargin<f64, F64Margin> for DerivedSpec<'_, O, f64>
620    where
621        O: DoFail,
622    {
623        fn is_close_to_with_margin(self, expected: f64, margin: impl Into<F64Margin>) -> Self {
624            self.expecting(is_close_to(expected).within_margin(margin))
625        }
626
627        fn is_not_close_to_with_margin(self, expected: f64, margin: impl Into<F64Margin>) -> Self {
628            self.expecting(not(is_close_to(expected).within_margin(margin)))
629        }
630    }
631
632    impl<O> AssertIsCloseToWithDefaultMargin<f64> for DerivedSpec<'_, O, f64>
633    where
634        O: DoFail,
635    {
636        fn is_close_to(self, expected: f64) -> Self {
637            self.expecting(is_close_to(expected).within_margin((4. * f64::EPSILON, 4)))
638        }
639
640        fn is_not_close_to(self, expected: f64) -> Self {
641            self.expecting(not(
642                is_close_to(expected).within_margin((4. * f64::EPSILON, 4))
643            ))
644        }
645    }
646}
647
648impl<O, S, E> AssertOrder<E> for DerivedSpec<'_, O, S>
649where
650    S: PartialOrd<E> + Debug,
651    E: Debug,
652    O: DoFail,
653{
654    fn is_less_than(self, expected: E) -> Self {
655        self.expecting(is_less_than(expected))
656    }
657
658    fn is_greater_than(self, expected: E) -> Self {
659        self.expecting(is_greater_than(expected))
660    }
661
662    fn is_at_most(self, expected: E) -> Self {
663        self.expecting(is_at_most(expected))
664    }
665
666    fn is_at_least(self, expected: E) -> Self {
667        self.expecting(is_at_least(expected))
668    }
669
670    fn is_before(self, expected: E) -> Self {
671        self.expecting(is_before(expected))
672    }
673
674    fn is_after(self, expected: E) -> Self {
675        self.expecting(is_after(expected))
676    }
677
678    fn is_between(self, min: E, max: E) -> Self {
679        self.expecting(is_between(min, max))
680    }
681}
682
683impl<O, S, E> AssertInRange<E> for DerivedSpec<'_, O, S>
684where
685    S: PartialOrd<E> + Debug,
686    E: PartialOrd<S> + Debug,
687    O: DoFail,
688{
689    fn is_in_range<R>(self, range: R) -> Self
690    where
691        R: RangeBounds<E> + Debug,
692    {
693        self.expecting(is_in_range(range))
694    }
695
696    fn is_not_in_range<R>(self, range: R) -> Self
697    where
698        R: RangeBounds<E> + Debug,
699    {
700        self.expecting(not(is_in_range(range)))
701    }
702}
703
704impl<O, S> AssertNumericIdentity for DerivedSpec<'_, O, S>
705where
706    S: AdditiveIdentityProperty + MultiplicativeIdentityProperty + PartialEq + Debug,
707    O: DoFail,
708{
709    fn is_zero(self) -> Self {
710        self.expecting(is_zero())
711    }
712
713    fn is_one(self) -> Self {
714        self.expecting(is_one())
715    }
716}
717
718impl<O, S> AssertSignum for DerivedSpec<'_, O, S>
719where
720    S: SignumProperty + Debug,
721    O: DoFail,
722{
723    fn is_negative(self) -> Self {
724        self.expecting(is_negative())
725    }
726
727    fn is_not_negative(self) -> Self {
728        self.expecting(not(is_negative()))
729    }
730
731    fn is_positive(self) -> Self {
732        self.expecting(is_positive())
733    }
734
735    fn is_not_positive(self) -> Self {
736        self.expecting(not(is_positive()))
737    }
738}
739
740impl<O, S> AssertInfinity for DerivedSpec<'_, O, S>
741where
742    S: InfinityProperty + Debug,
743    O: DoFail,
744{
745    fn is_infinite(self) -> Self {
746        self.expecting(is_infinite())
747    }
748
749    fn is_finite(self) -> Self {
750        self.expecting(is_finite())
751    }
752}
753
754impl<O, S> AssertNotANumber for DerivedSpec<'_, O, S>
755where
756    S: IsNanProperty + Debug,
757    O: DoFail,
758{
759    fn is_not_a_number(self) -> Self {
760        self.expecting(not(is_a_number()))
761    }
762
763    fn is_a_number(self) -> Self {
764        self.expecting(is_a_number())
765    }
766}
767
768impl<O, S> AssertDecimalNumber for DerivedSpec<'_, O, S>
769where
770    S: DecimalProperties + Debug,
771    O: DoFail,
772{
773    fn has_scale_of(self, expected_scale: i64) -> Self {
774        self.expecting(has_scale_of(expected_scale))
775    }
776
777    fn has_precision_of(self, expected_precision: u64) -> Self {
778        self.expecting(has_precision_of(expected_precision))
779    }
780
781    fn is_integer(self) -> Self {
782        self.expecting(is_integer())
783    }
784}
785
786impl<O> AssertBoolean for DerivedSpec<'_, O, bool>
787where
788    O: DoFail,
789{
790    fn is_true(self) -> Self {
791        self.expecting(is_true())
792    }
793
794    fn is_false(self) -> Self {
795        self.expecting(is_false())
796    }
797}
798
799impl<O> AssertChar for DerivedSpec<'_, O, char>
800where
801    O: DoFail,
802{
803    fn is_lowercase(self) -> Self {
804        self.expecting(is_lower_case())
805    }
806
807    fn is_uppercase(self) -> Self {
808        self.expecting(is_upper_case())
809    }
810
811    fn is_ascii(self) -> Self {
812        self.expecting(is_ascii())
813    }
814
815    fn is_alphabetic(self) -> Self {
816        self.expecting(is_alphabetic())
817    }
818
819    fn is_alphanumeric(self) -> Self {
820        self.expecting(is_alphanumeric())
821    }
822
823    fn is_control_char(self) -> Self {
824        self.expecting(is_control_char())
825    }
826
827    fn is_digit(self, radix: u32) -> Self {
828        self.expecting(is_digit(radix))
829    }
830
831    fn is_whitespace(self) -> Self {
832        self.expecting(is_whitespace())
833    }
834}
835
836impl<O> AssertChar for DerivedSpec<'_, O, &char>
837where
838    O: DoFail,
839{
840    fn is_lowercase(self) -> Self {
841        self.expecting(is_lower_case())
842    }
843
844    fn is_uppercase(self) -> Self {
845        self.expecting(is_upper_case())
846    }
847
848    fn is_ascii(self) -> Self {
849        self.expecting(is_ascii())
850    }
851
852    fn is_alphabetic(self) -> Self {
853        self.expecting(is_alphabetic())
854    }
855
856    fn is_alphanumeric(self) -> Self {
857        self.expecting(is_alphanumeric())
858    }
859
860    fn is_control_char(self) -> Self {
861        self.expecting(is_control_char())
862    }
863
864    fn is_digit(self, radix: u32) -> Self {
865        self.expecting(is_digit(radix))
866    }
867
868    fn is_whitespace(self) -> Self {
869        self.expecting(is_whitespace())
870    }
871}
872
873impl<O, S> AssertEmptiness for DerivedSpec<'_, O, S>
874where
875    S: IsEmptyProperty + Debug,
876    O: DoFail,
877{
878    fn is_empty(self) -> Self {
879        self.expecting(is_empty())
880    }
881
882    fn is_not_empty(self) -> Self {
883        self.expecting(not(is_empty()))
884    }
885}
886
887impl<O, S> AssertHasLength<usize> for DerivedSpec<'_, O, S>
888where
889    S: LengthProperty + Debug,
890    O: DoFail,
891{
892    fn has_length(self, expected_length: usize) -> Self {
893        self.expecting(has_length(expected_length))
894    }
895
896    fn has_length_in_range<R>(self, expected_range: R) -> Self
897    where
898        R: RangeBounds<usize> + Debug,
899    {
900        self.expecting(has_length_in_range(expected_range))
901    }
902
903    fn has_length_less_than(self, expected_length: usize) -> Self {
904        self.expecting(has_length_less_than(expected_length))
905    }
906
907    fn has_length_greater_than(self, expected_length: usize) -> Self {
908        self.expecting(has_length_greater_than(expected_length))
909    }
910
911    fn has_at_most_length(self, expected_length: usize) -> Self {
912        self.expecting(has_at_most_length(expected_length))
913    }
914
915    fn has_at_least_length(self, expected_length: usize) -> Self {
916        self.expecting(has_at_least_length(expected_length))
917    }
918}
919
920impl<O, S> AssertHasCharCount<usize> for DerivedSpec<'_, O, S>
921where
922    S: CharCountProperty + Debug,
923    O: DoFail,
924{
925    fn has_char_count(self, expected_char_count: usize) -> Self {
926        self.expecting(has_char_count(expected_char_count))
927    }
928
929    fn has_char_count_in_range<U>(self, expected_range: U) -> Self
930    where
931        U: RangeBounds<usize> + Debug,
932    {
933        self.expecting(has_char_count_in_range(expected_range))
934    }
935
936    fn has_char_count_less_than(self, expected_char_count: usize) -> Self {
937        self.expecting(has_char_count_less_than(expected_char_count))
938    }
939
940    fn has_char_count_greater_than(self, expected_char_count: usize) -> Self {
941        self.expecting(has_char_count_greater_than(expected_char_count))
942    }
943
944    fn has_at_most_char_count(self, expected_char_count: usize) -> Self {
945        self.expecting(has_at_most_char_count(expected_char_count))
946    }
947
948    fn has_at_least_char_count(self, expected_char_count: usize) -> Self {
949        self.expecting(has_at_least_char_count(expected_char_count))
950    }
951}
952
953impl<O, S> AssertOption for DerivedSpec<'_, O, Option<S>>
954where
955    S: Debug,
956    O: DoFail,
957{
958    fn is_some(self) -> Self {
959        self.expecting(is_some())
960    }
961
962    fn is_none(self) -> Self {
963        self.expecting(is_none())
964    }
965}
966
967impl<'a, O, T> AssertOptionValue for DerivedSpec<'a, O, Option<T>>
968where
969    O: DoFail,
970{
971    type Some = DerivedSpec<'a, O, T>;
972
973    fn some(self) -> Self::Some {
974        self.mapping(|subject| match subject {
975            None => {
976                panic!("expected the subject to be `Some(_)`, but was `None`")
977            },
978            Some(value) => value,
979        })
980    }
981}
982
983impl<'a, O, T> AssertOptionValue for DerivedSpec<'a, O, &'a Option<T>>
984where
985    T: 'a,
986    O: DoFail,
987{
988    type Some = DerivedSpec<'a, O, &'a T>;
989
990    fn some(self) -> Self::Some {
991        self.mapping(|subject| match subject {
992            None => {
993                panic!("expected the subject to be `Some(_)`, but was `None`")
994            },
995            Some(value) => value,
996        })
997    }
998}
999
1000impl<O, T, E> AssertHasValue<E> for DerivedSpec<'_, O, Option<T>>
1001where
1002    T: PartialEq<E> + Debug,
1003    E: Debug,
1004    O: DoFail,
1005{
1006    fn has_value(self, expected: E) -> Self {
1007        self.expecting(has_value(expected))
1008    }
1009}
1010
1011impl<O, T, E> AssertHasValue<E> for DerivedSpec<'_, O, &Option<T>>
1012where
1013    T: PartialEq<E> + Debug,
1014    E: Debug,
1015    O: DoFail,
1016{
1017    fn has_value(self, expected: E) -> Self {
1018        self.expecting(has_value(expected))
1019    }
1020}
1021
1022impl<O, T, E> AssertResult for DerivedSpec<'_, O, Result<T, E>>
1023where
1024    T: Debug,
1025    E: Debug,
1026    O: DoFail,
1027{
1028    fn is_ok(self) -> Self {
1029        self.expecting(is_ok())
1030    }
1031
1032    fn is_err(self) -> Self {
1033        self.expecting(is_err())
1034    }
1035}
1036
1037impl<O, T, E> AssertResult for DerivedSpec<'_, O, &Result<T, E>>
1038where
1039    T: Debug,
1040    E: Debug,
1041    O: DoFail,
1042{
1043    fn is_ok(self) -> Self {
1044        self.expecting(is_ok())
1045    }
1046
1047    fn is_err(self) -> Self {
1048        self.expecting(is_err())
1049    }
1050}
1051
1052impl<'a, O, T, E> AssertResultValue for DerivedSpec<'a, O, Result<T, E>>
1053where
1054    T: Debug,
1055    E: Debug,
1056    O: DoFail,
1057{
1058    type Ok = DerivedSpec<'a, O, T>;
1059    type Err = DerivedSpec<'a, O, E>;
1060
1061    fn ok(self) -> Self::Ok {
1062        self.mapping(|subject| match subject {
1063            Ok(value) => value,
1064            Err(error) => {
1065                panic!("expected the subject to be `Ok(_)`, but was `Err({error:?})`")
1066            },
1067        })
1068    }
1069
1070    fn err(self) -> Self::Err {
1071        self.mapping(|subject| match subject {
1072            Ok(value) => {
1073                panic!("expected the subject to be `Err(_)`, but was `Ok({value:?})`")
1074            },
1075            Err(error) => error,
1076        })
1077    }
1078}
1079
1080impl<'a, O, T, E> AssertResultValue for DerivedSpec<'a, O, &'a Result<T, E>>
1081where
1082    T: Debug,
1083    E: Debug,
1084    O: DoFail,
1085{
1086    type Ok = DerivedSpec<'a, O, &'a T>;
1087    type Err = DerivedSpec<'a, O, &'a E>;
1088
1089    fn ok(self) -> Self::Ok {
1090        self.mapping(|subject| match subject {
1091            Ok(value) => value,
1092            Err(error) => {
1093                panic!("expected the subject to be `Ok(_)`, but was `Err({error:?})`")
1094            },
1095        })
1096    }
1097
1098    fn err(self) -> Self::Err {
1099        self.mapping(|subject| match subject {
1100            Ok(value) => {
1101                panic!("expected the subject to be `Err(_)`, but was `Ok({value:?})`")
1102            },
1103            Err(error) => error,
1104        })
1105    }
1106}
1107
1108impl<O, T, E, X> AssertHasValue<X> for DerivedSpec<'_, O, Result<T, E>>
1109where
1110    T: PartialEq<X> + Debug,
1111    E: Debug,
1112    X: Debug,
1113    O: DoFail,
1114{
1115    fn has_value(self, expected: X) -> Self {
1116        self.expecting(has_value(expected))
1117    }
1118}
1119
1120impl<O, T, E, X> AssertHasValue<X> for DerivedSpec<'_, O, &Result<T, E>>
1121where
1122    T: PartialEq<X> + Debug,
1123    E: Debug,
1124    X: Debug,
1125    O: DoFail,
1126{
1127    fn has_value(self, expected: X) -> Self {
1128        self.expecting(has_value(expected))
1129    }
1130}
1131
1132impl<O, T, E, X> AssertHasError<X> for DerivedSpec<'_, O, Result<T, E>>
1133where
1134    T: Debug,
1135    E: PartialEq<X> + Debug,
1136    X: Debug,
1137    O: DoFail,
1138{
1139    fn has_error(self, expected: X) -> Self {
1140        self.expecting(has_error(expected))
1141    }
1142}
1143
1144impl<O, T, E, X> AssertHasError<X> for DerivedSpec<'_, O, &Result<T, E>>
1145where
1146    T: Debug,
1147    E: PartialEq<X> + Debug,
1148    X: Debug,
1149    O: DoFail,
1150{
1151    fn has_error(self, expected: X) -> Self {
1152        self.expecting(has_error(expected))
1153    }
1154}
1155
1156impl<'a, O, T, E, X> AssertHasErrorMessage<X> for DerivedSpec<'a, O, Result<T, E>>
1157where
1158    T: Debug,
1159    E: Display,
1160    X: Debug,
1161    String: PartialEq<X>,
1162    O: DoFail,
1163{
1164    type ErrorMessage = DerivedSpec<'a, O, String>;
1165
1166    fn has_error_message(self, expected: X) -> Self::ErrorMessage {
1167        self.mapping(|result| match result {
1168            Ok(value) => panic!("expected the subject to be `Err(_)` with message {expected:?}, but was `Ok({value:?})`"),
1169            Err(error) => error.to_string(),
1170        }).expecting(is_equal_to(expected))
1171    }
1172}
1173
1174impl<'a, O, T, E, X> AssertHasErrorMessage<X> for DerivedSpec<'a, O, &Result<T, E>>
1175where
1176    T: Debug,
1177    E: Display,
1178    X: Debug,
1179    String: PartialEq<X>,
1180    O: DoFail,
1181{
1182    type ErrorMessage = DerivedSpec<'a, O, String>;
1183
1184    fn has_error_message(self, expected: X) -> Self::ErrorMessage {
1185        self.mapping(|result| match result {
1186            Ok(value) => panic!("expected the subject to be `Err(_)` with message {expected:?}, but was `Ok({value:?})`"),
1187            Err(error) => error.to_string(),
1188        }).expecting(is_equal_to(expected))
1189    }
1190}
1191
1192impl<'a, O, S> AssertErrorHasSource for DerivedSpec<'a, O, S>
1193where
1194    S: Error,
1195    O: DoFail,
1196{
1197    type SourceMessage = DerivedSpec<'a, O, Option<String>>;
1198
1199    fn has_no_source(self) -> Self {
1200        self.expecting(not(error_has_source()))
1201    }
1202
1203    fn has_source(self) -> Self {
1204        self.expecting(error_has_source())
1205    }
1206
1207    fn has_source_message(self, expected_source_message: impl Into<String>) -> Self::SourceMessage {
1208        let expected_source_message = expected_source_message.into();
1209        self.expecting(error_has_source_message(expected_source_message))
1210            .mapping(|err| err.source().map(ToString::to_string))
1211    }
1212}
1213
1214impl<O, S, E> AssertHasDebugString<E> for DerivedSpec<'_, O, S>
1215where
1216    S: Debug,
1217    E: AsRef<str>,
1218    O: DoFail,
1219{
1220    fn has_debug_string(self, expected: E) -> Self {
1221        self.expecting(has_debug_string(expected))
1222    }
1223
1224    fn does_not_have_debug_string(self, expected: E) -> Self {
1225        self.expecting(not(has_debug_string(expected)))
1226    }
1227}
1228
1229impl<'a, O, S> AssertDebugString for DerivedSpec<'a, O, S>
1230where
1231    S: Debug,
1232    O: DoFail,
1233{
1234    type DebugString = DerivedSpec<'a, O, String>;
1235
1236    fn debug_string(self) -> Self::DebugString {
1237        let expression_debug_string = format!("{}'s debug string", self.expression);
1238        self.mapping(|subject| format!("{subject:?}"))
1239            .named(expression_debug_string)
1240    }
1241}
1242
1243impl<O, S, E> AssertHasDisplayString<E> for DerivedSpec<'_, O, S>
1244where
1245    S: Display,
1246    E: AsRef<str>,
1247    O: DoFail,
1248{
1249    fn has_display_string(self, expected: E) -> Self {
1250        self.expecting(has_display_string(expected))
1251    }
1252
1253    fn does_not_have_display_string(self, expected: E) -> Self {
1254        self.expecting(not(has_display_string(expected)))
1255    }
1256}
1257
1258impl<'a, O, S> AssertDisplayString for DerivedSpec<'a, O, S>
1259where
1260    S: Display,
1261    O: DoFail,
1262{
1263    type DisplayString = DerivedSpec<'a, O, String>;
1264
1265    fn display_string(self) -> Self::DisplayString {
1266        let expression_display_string = format!("{}'s display string", self.expression);
1267        self.mapping(|subject| subject.to_string())
1268            .named(expression_display_string)
1269    }
1270}
1271
1272impl<'a, O, S> AssertStringPattern<&'a str> for DerivedSpec<'a, O, S>
1273where
1274    S: 'a + AsRef<str> + Debug,
1275    O: DoFail,
1276{
1277    fn contains(self, pattern: &'a str) -> Self {
1278        self.expecting(string_contains(pattern))
1279    }
1280
1281    fn does_not_contain(self, pattern: &'a str) -> Self {
1282        self.expecting(not(string_contains(pattern)))
1283    }
1284
1285    fn starts_with(self, pattern: &'a str) -> Self {
1286        self.expecting(string_starts_with(pattern))
1287    }
1288
1289    fn does_not_start_with(self, pattern: &'a str) -> Self {
1290        self.expecting(not(string_starts_with(pattern)))
1291    }
1292
1293    fn ends_with(self, pattern: &'a str) -> Self {
1294        self.expecting(string_ends_with(pattern))
1295    }
1296
1297    fn does_not_end_with(self, pattern: &'a str) -> Self {
1298        self.expecting(not(string_ends_with(pattern)))
1299    }
1300}
1301
1302impl<'a, O, S> AssertStringPattern<String> for DerivedSpec<'a, O, S>
1303where
1304    S: 'a + AsRef<str> + Debug,
1305    O: DoFail,
1306{
1307    fn contains(self, pattern: String) -> Self {
1308        self.expecting(string_contains(pattern))
1309    }
1310
1311    fn does_not_contain(self, pattern: String) -> Self {
1312        self.expecting(not(string_contains(pattern)))
1313    }
1314
1315    fn starts_with(self, pattern: String) -> Self {
1316        self.expecting(string_starts_with(pattern))
1317    }
1318
1319    fn does_not_start_with(self, pattern: String) -> Self {
1320        self.expecting(not(string_starts_with(pattern)))
1321    }
1322
1323    fn ends_with(self, pattern: String) -> Self {
1324        self.expecting(string_ends_with(pattern))
1325    }
1326
1327    fn does_not_end_with(self, pattern: String) -> Self {
1328        self.expecting(not(string_ends_with(pattern)))
1329    }
1330}
1331
1332impl<'a, O, S> AssertStringPattern<char> for DerivedSpec<'a, O, S>
1333where
1334    S: 'a + AsRef<str> + Debug,
1335    O: DoFail,
1336{
1337    fn contains(self, pattern: char) -> Self {
1338        self.expecting(string_contains(pattern))
1339    }
1340
1341    fn does_not_contain(self, pattern: char) -> Self {
1342        self.expecting(not(string_contains(pattern)))
1343    }
1344
1345    fn starts_with(self, pattern: char) -> Self {
1346        self.expecting(string_starts_with(pattern))
1347    }
1348
1349    fn does_not_start_with(self, pattern: char) -> Self {
1350        self.expecting(not(string_starts_with(pattern)))
1351    }
1352
1353    fn ends_with(self, pattern: char) -> Self {
1354        self.expecting(string_ends_with(pattern))
1355    }
1356
1357    fn does_not_end_with(self, pattern: char) -> Self {
1358        self.expecting(not(string_ends_with(pattern)))
1359    }
1360}
1361
1362impl<'a, O, S> AssertStringContainsAnyOf<&'a [char]> for DerivedSpec<'a, O, S>
1363where
1364    S: 'a + AsRef<str> + Debug,
1365    O: DoFail,
1366{
1367    fn contains_any_of(self, expected: &'a [char]) -> Self {
1368        self.expecting(string_contains_any_of(expected))
1369    }
1370
1371    fn does_not_contain_any_of(self, expected: &'a [char]) -> Self {
1372        self.expecting(not(string_contains_any_of(expected)))
1373    }
1374}
1375
1376impl<'a, O, S, const N: usize> AssertStringContainsAnyOf<[char; N]> for DerivedSpec<'a, O, S>
1377where
1378    S: 'a + AsRef<str> + Debug,
1379    O: DoFail,
1380{
1381    fn contains_any_of(self, expected: [char; N]) -> Self {
1382        self.expecting(string_contains_any_of(expected))
1383    }
1384
1385    fn does_not_contain_any_of(self, expected: [char; N]) -> Self {
1386        self.expecting(not(string_contains_any_of(expected)))
1387    }
1388}
1389
1390impl<'a, O, S, const N: usize> AssertStringContainsAnyOf<&'a [char; N]> for DerivedSpec<'a, O, S>
1391where
1392    S: 'a + AsRef<str> + Debug,
1393    O: DoFail,
1394{
1395    fn contains_any_of(self, expected: &'a [char; N]) -> Self {
1396        self.expecting(string_contains_any_of(expected))
1397    }
1398
1399    fn does_not_contain_any_of(self, expected: &'a [char; N]) -> Self {
1400        self.expecting(not(string_contains_any_of(expected)))
1401    }
1402}
1403
1404#[cfg(feature = "regex")]
1405mod regex {
1406    use crate::assertions::AssertStringMatches;
1407    use crate::derived_spec::DerivedSpec;
1408    use crate::expectations::{not, string_matches};
1409    use crate::spec::{DoFail, Expecting};
1410    use crate::std::fmt::Debug;
1411
1412    impl<O, S> AssertStringMatches for DerivedSpec<'_, O, S>
1413    where
1414        S: AsRef<str> + Debug,
1415        O: DoFail,
1416    {
1417        fn matches(self, regex_pattern: &str) -> Self {
1418            self.expecting(string_matches(regex_pattern))
1419        }
1420
1421        fn does_not_match(self, regex_pattern: &str) -> Self {
1422            self.expecting(not(string_matches(regex_pattern)))
1423        }
1424    }
1425}
1426
1427impl<'a, O, S, T, E> AssertIteratorContains<E> for DerivedSpec<'a, O, S>
1428where
1429    S: IntoIterator<Item = T>,
1430    T: PartialEq<E> + Debug,
1431    E: Debug,
1432    O: DoFail,
1433{
1434    type Sequence = DerivedSpec<'a, O, Vec<T>>;
1435
1436    fn contains(self, element: E) -> Self::Sequence {
1437        self.mapping(Vec::from_iter)
1438            .expecting(iterator_contains(element))
1439    }
1440
1441    fn does_not_contain(self, element: E) -> Self::Sequence {
1442        self.mapping(Vec::from_iter)
1443            .expecting(not(iterator_contains(element)))
1444    }
1445}
1446
1447impl<'a, O, S, T, E> AssertIteratorContainsInAnyOrder<E> for DerivedSpec<'a, O, S>
1448where
1449    S: IntoIterator<Item = T>,
1450    T: PartialEq<<E as IntoIterator>::Item> + Debug,
1451    E: IntoIterator,
1452    <E as IntoIterator>::Item: Debug,
1453    O: DoFail,
1454{
1455    type Sequence = DerivedSpec<'a, O, Vec<T>>;
1456
1457    fn contains_exactly_in_any_order(self, expected: E) -> Self::Sequence {
1458        self.mapping(Vec::from_iter)
1459            .expecting(iterator_contains_exactly_in_any_order(expected))
1460    }
1461
1462    fn contains_any_of(self, expected: E) -> Self::Sequence {
1463        self.mapping(Vec::from_iter)
1464            .expecting(iterator_contains_any_of(expected))
1465    }
1466
1467    fn does_not_contain_any_of(self, expected: E) -> Self::Sequence {
1468        self.mapping(Vec::from_iter)
1469            .expecting(not(iterator_contains_any_of(expected)))
1470    }
1471
1472    fn contains_all_of(self, expected: E) -> Self::Sequence {
1473        self.mapping(Vec::from_iter)
1474            .expecting(iterator_contains_all_of(expected))
1475    }
1476
1477    fn contains_only(self, expected: E) -> Self::Sequence {
1478        self.mapping(Vec::from_iter)
1479            .expecting(iterator_contains_only(expected))
1480    }
1481
1482    fn contains_only_once(self, expected: E) -> Self::Sequence {
1483        self.mapping(Vec::from_iter)
1484            .expecting(iterator_contains_only_once(expected))
1485    }
1486}
1487
1488impl<'a, O, S, T, E> AssertIteratorContainsInOrder<E> for DerivedSpec<'a, O, S>
1489where
1490    S: IntoIterator<Item = T>,
1491    <S as IntoIterator>::IntoIter: DefinedOrderProperty,
1492    E: IntoIterator,
1493    <E as IntoIterator>::IntoIter: DefinedOrderProperty,
1494    <E as IntoIterator>::Item: Debug,
1495    T: PartialEq<<E as IntoIterator>::Item> + Debug,
1496    O: DoFail,
1497{
1498    type Sequence = DerivedSpec<'a, O, Vec<T>>;
1499
1500    fn contains_exactly(self, expected: E) -> Self::Sequence {
1501        self.mapping(Vec::from_iter)
1502            .expecting(iterator_contains_exactly(expected))
1503    }
1504
1505    fn contains_sequence(self, expected: E) -> Self::Sequence {
1506        self.mapping(Vec::from_iter)
1507            .expecting(iterator_contains_sequence(expected))
1508    }
1509
1510    fn contains_all_in_order(self, expected: E) -> Self::Sequence {
1511        self.mapping(Vec::from_iter)
1512            .expecting(iterator_contains_all_in_order(expected))
1513    }
1514
1515    fn starts_with(self, expected: E) -> Self::Sequence {
1516        self.mapping(Vec::from_iter)
1517            .expecting(iterator_starts_with(expected))
1518    }
1519
1520    fn ends_with(self, expected: E) -> Self::Sequence {
1521        self.mapping(Vec::from_iter)
1522            .expecting(iterator_ends_with(expected))
1523    }
1524}
1525
1526impl<O, S, E> AssertMapContainsKey<E> for DerivedSpec<'_, O, S>
1527where
1528    S: MapProperties + Debug,
1529    <S as MapProperties>::Key: PartialEq<E> + Debug,
1530    <S as MapProperties>::Value: Debug,
1531    E: Debug,
1532    O: DoFail,
1533{
1534    fn contains_key(self, expected_key: E) -> Self {
1535        self.expecting(map_contains_key(expected_key))
1536    }
1537
1538    fn does_not_contain_key(self, expected_key: E) -> Self {
1539        self.expecting(not(map_contains_key(expected_key)))
1540    }
1541
1542    fn contains_keys(self, expected_keys: impl IntoIterator<Item = E>) -> Self {
1543        self.expecting(map_contains_keys(expected_keys))
1544    }
1545
1546    fn does_not_contain_keys(self, expected_keys: impl IntoIterator<Item = E>) -> Self {
1547        self.expecting(map_does_not_contain_keys(expected_keys))
1548    }
1549
1550    fn contains_exactly_keys(self, expected_keys: impl IntoIterator<Item = E>) -> Self {
1551        self.expecting(map_contains_exactly_keys(expected_keys))
1552    }
1553}
1554
1555impl<O, S, E> AssertMapContainsValue<E> for DerivedSpec<'_, O, S>
1556where
1557    S: MapProperties + Debug,
1558    <S as MapProperties>::Key: Debug,
1559    <S as MapProperties>::Value: PartialEq<E> + Debug,
1560    E: Debug,
1561    O: DoFail,
1562{
1563    fn contains_value(self, expected_value: E) -> Self {
1564        self.expecting(map_contains_value(expected_value))
1565    }
1566
1567    fn does_not_contain_value(self, expected_value: E) -> Self {
1568        self.expecting(not(map_contains_value(expected_value)))
1569    }
1570
1571    fn contains_values(self, expected_values: impl IntoIterator<Item = E>) -> Self {
1572        self.expecting(map_contains_values(expected_values))
1573    }
1574
1575    fn does_not_contain_values(self, expected_values: impl IntoIterator<Item = E>) -> Self {
1576        self.expecting(map_does_not_contain_values(expected_values))
1577    }
1578}
1579
1580impl<'a, O, S, T> AssertOrderedElements for DerivedSpec<'a, O, S>
1581where
1582    S: IntoIterator<Item = T>,
1583    <S as IntoIterator>::IntoIter: DefinedOrderProperty,
1584    T: Debug,
1585    O: DoFail + GetFailures,
1586{
1587    type SingleElement = DerivedSpec<'a, O, T>;
1588    type MultipleElements = DerivedSpec<'a, O, Vec<T>>;
1589
1590    fn first_element(self) -> Self::SingleElement {
1591        let spec = self
1592            .mapping(Vec::from_iter)
1593            .expecting(has_at_least_number_of_elements(1));
1594        if spec.has_failures() {
1595            PanicOnFail.do_fail_with(&spec.failures());
1596            unreachable!("Assertion failed and should have panicked! Please report a bug.")
1597        }
1598        let orig_subject_name = spec.expression();
1599        let new_subject_name = format!("the first element of {orig_subject_name}");
1600        spec.extracting("", |mut collection| collection.remove(0))
1601            .named(new_subject_name)
1602    }
1603
1604    fn last_element(self) -> Self::SingleElement {
1605        let spec = self
1606            .mapping(Vec::from_iter)
1607            .expecting(has_at_least_number_of_elements(1));
1608        if spec.has_failures() {
1609            PanicOnFail.do_fail_with(&spec.failures());
1610            unreachable!("Assertion failed and should have panicked! Please report a bug.")
1611        }
1612        let orig_subject_name = spec.expression();
1613        let new_subject_name = format!("the last element of {orig_subject_name}");
1614        spec.extracting("", |mut collection| {
1615            collection.pop().unwrap_or_else(|| {
1616                unreachable!("Assertion failed and should have panicked! Please report a bug.")
1617            })
1618        })
1619        .named(new_subject_name)
1620    }
1621
1622    fn nth_element(self, n: usize) -> Self::SingleElement {
1623        let min_len = n + 1;
1624        let spec = self
1625            .mapping(Vec::from_iter)
1626            .expecting(has_at_least_number_of_elements(min_len));
1627        if spec.has_failures() {
1628            PanicOnFail.do_fail_with(&spec.failures());
1629            unreachable!("Assertion failed and should have panicked! Please report a bug.")
1630        }
1631        let orig_subject_name = spec.expression();
1632        let new_subject_name = format!("{orig_subject_name}[{n}]");
1633        spec.extracting("", |mut collection| collection.remove(n))
1634            .named(new_subject_name)
1635    }
1636
1637    fn elements_at(self, indices: impl IntoIterator<Item = usize>) -> Self::MultipleElements {
1638        let indices = Vec::from_iter(indices);
1639        let orig_subject_name = self.expression();
1640        let new_subject_name = format!("{orig_subject_name} at positions {indices:?}");
1641        let indices = HashSet::<_>::from_iter(indices);
1642        self.mapping(|subject| {
1643            subject
1644                .into_iter()
1645                .enumerate()
1646                .filter_map(|(i, v)| if indices.contains(&i) { Some(v) } else { None })
1647                .collect()
1648        })
1649        .named(new_subject_name)
1650    }
1651}
1652
1653impl<'a, O, I> AssertElements<'a, I> for DerivedSpec<'a, O, I>
1654where
1655    I: 'a + IntoIterator,
1656    O: DoFail + GetLocation<'a>,
1657{
1658    type Output = DerivedSpec<'a, O, ()>;
1659
1660    fn each_element<A, B>(mut self, assert: A) -> Self::Output
1661    where
1662        A: Fn(Spec<'a, <I as IntoIterator>::Item, CollectFailures>) -> B,
1663        B: GetFailures,
1664    {
1665        let root_expression = &self.expression;
1666        let diff_format = self.diff_format().clone();
1667        let location = self.location();
1668        let mut collected_failures = Vec::new();
1669        let mut position = -1;
1670        for item in self.subject {
1671            position += 1;
1672            let mut element_spec = Spec::new(item, CollectFailures)
1673                .named(format!("{root_expression}[{position}]"))
1674                .with_diff_format(diff_format.clone());
1675            if let Some(location) = location {
1676                element_spec = element_spec.located_at(location);
1677            }
1678            let failures = assert(element_spec).failures();
1679            collected_failures.extend(failures);
1680        }
1681        if !collected_failures.is_empty() {
1682            self.original.do_fail_with(collected_failures);
1683        }
1684        DerivedSpec {
1685            original: self.original,
1686            subject: (),
1687            expression: self.expression,
1688            diff_format: self.diff_format,
1689        }
1690    }
1691
1692    fn any_element<A, B>(mut self, assert: A) -> Self::Output
1693    where
1694        A: Fn(Spec<'a, <I as IntoIterator>::Item, CollectFailures>) -> B,
1695        B: GetFailures,
1696    {
1697        let root_expression = &self.expression;
1698        let diff_format = self.diff_format().clone();
1699        let location = self.location();
1700        let mut collected_failures = Vec::new();
1701        let mut any_success = false;
1702        let mut position = -1;
1703        for item in self.subject {
1704            position += 1;
1705            let mut element_spec = Spec::new(item, CollectFailures)
1706                .named(format!("{root_expression}[{position}]"))
1707                .with_diff_format(diff_format.clone());
1708            if let Some(location) = location {
1709                element_spec = element_spec.located_at(location);
1710            }
1711            let failures = assert(element_spec).failures();
1712            if failures.is_empty() {
1713                any_success = true;
1714                break;
1715            }
1716            collected_failures.extend(failures);
1717        }
1718        if !any_success {
1719            self.original.do_fail_with(collected_failures);
1720        }
1721        DerivedSpec {
1722            original: self.original,
1723            subject: (),
1724            expression: self.expression,
1725            diff_format: self.diff_format,
1726        }
1727    }
1728}
1729
1730impl<'a, O, S, T, U> AssertOrderedElementsRef for DerivedSpec<'a, O, S>
1731where
1732    S: IntoIterator<Item = T>,
1733    <S as IntoIterator>::IntoIter: DefinedOrderProperty,
1734    T: ToOwned<Owned = U> + Debug,
1735    O: DoFail + GetFailures,
1736{
1737    type SingleElement = DerivedSpec<'a, DerivedSpec<'a, O, Vec<T>>, U>;
1738    type MultipleElements = DerivedSpec<'a, DerivedSpec<'a, O, Vec<T>>, Vec<U>>;
1739
1740    fn first_element_ref(self) -> Self::SingleElement {
1741        let original_spec = self
1742            .mapping(Vec::from_iter)
1743            .expecting(has_at_least_number_of_elements(1));
1744        if original_spec.has_failures() {
1745            PanicOnFail.do_fail_with(&original_spec.failures());
1746            unreachable!("Assertion failed and should have panicked! Please report a bug.")
1747        }
1748        let orig_subject_name = original_spec.expression();
1749        let new_subject_name = format!("the first element of {orig_subject_name}");
1750        original_spec.extracting_ref("", |collection|
1751            collection.first()
1752                .unwrap_or_else(||
1753                    unreachable!("We should have asserted before, that there is at least one element in the collection/iterator. Please file a bug.")
1754                )
1755        ).named(new_subject_name)
1756    }
1757
1758    fn last_element_ref(self) -> Self::SingleElement {
1759        let original_spec = self
1760            .mapping(Vec::from_iter)
1761            .expecting(has_at_least_number_of_elements(1));
1762        if original_spec.has_failures() {
1763            PanicOnFail.do_fail_with(&original_spec.failures());
1764            unreachable!("Assertion failed and should have panicked! Please report a bug.")
1765        }
1766        let orig_subject_name = original_spec.expression();
1767        let new_subject_name = format!("the last element of {orig_subject_name}");
1768        original_spec.extracting_ref("", |collection|
1769            collection.last()
1770                .unwrap_or_else(||
1771                    unreachable!("We should have asserted before, that there is at least one element in the collection/iterator. Please file a bug.")
1772                )
1773        ).named(new_subject_name)
1774    }
1775
1776    fn nth_element_ref(self, n: usize) -> Self::SingleElement {
1777        let min_len = n + 1;
1778        let original_spec = self
1779            .mapping(Vec::from_iter)
1780            .expecting(has_at_least_number_of_elements(min_len));
1781        if original_spec.has_failures() {
1782            PanicOnFail.do_fail_with(&original_spec.failures());
1783            unreachable!("Assertion failed and should have panicked! Please report a bug.")
1784        }
1785        let orig_subject_name = original_spec.expression();
1786        let new_subject_name = format!("{orig_subject_name}[{n}]");
1787        original_spec.extracting_ref("", |collection|
1788            collection.get(n)
1789                .unwrap_or_else(||
1790                    unreachable!("We should have asserted before, that there is at least one element in the collection/iterator. Please file a bug.")
1791                )
1792        ).named(new_subject_name)
1793    }
1794
1795    fn elements_ref_at(self, indices: impl IntoIterator<Item = usize>) -> Self::MultipleElements {
1796        let indices = Vec::from_iter(indices);
1797        let orig_subject_name = self.expression();
1798        let new_subject_name = format!("{orig_subject_name} at positions {indices:?}");
1799        let indices = HashSet::<_>::from_iter(indices);
1800        let original_spec = self.mapping(Vec::from_iter);
1801        original_spec
1802            .extracting_ref_iter("", |collection| {
1803                collection
1804                    .enumerate()
1805                    .filter_map(|(i, e)| {
1806                        if indices.contains(&i) {
1807                            Some(e.to_owned())
1808                        } else {
1809                            None
1810                        }
1811                    })
1812                    .collect()
1813            })
1814            .named(new_subject_name)
1815    }
1816}
1817
1818#[cfg(test)]
1819mod tests;