Skip to main content

refining_core/
predicate.rs

1//! Core predicate traits.
2
3use core::{fmt, marker::PhantomData};
4
5/// Represents predicates over values of type `T`.
6pub trait Predicate<T: ?Sized> {
7    /// Checks the given reference to value of type `T`.
8    ///
9    /// Returns [`true`] if the predicate is satisfied by this value, [`false`] otherwise.
10    fn check(value: &T) -> bool;
11
12    /// Checks the given value of type `T`.
13    ///
14    /// Returns [`true`] if the predicate is satisfied by this value, [`false`] otherwise.
15    ///
16    /// The default implementation simply calls [`check`] with value reference.
17    ///
18    /// [`check`]: Self::check
19    fn check_value(value: T) -> bool
20    where
21        T: Sized,
22    {
23        Self::check(&value)
24    }
25
26    /// Formats the expectation of this predicate into the given formatter.
27    ///
28    /// # Errors
29    ///
30    /// Returns [`fmt::Error`] in case formatting fails.
31    fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
32
33    /// Formats the expectation code of this predicate into the given formatter.
34    ///
35    /// # Errors
36    ///
37    /// Returns [`fmt::Error`] in case formatting fails.
38    fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
39}
40
41/// Extends values `P` implementing [`Predicate<T>`] to return [`Expected<T, P>`] for formatting.
42pub trait PredicateExpected<T: ?Sized>: Predicate<T> {
43    /// Returns the [`Expected<T, Self>`] value used for formatting.
44    #[must_use]
45    fn expected() -> Expected<T, Self> {
46        Expected::new()
47    }
48}
49
50impl<T: ?Sized, P: Predicate<T> + ?Sized> PredicateExpected<T> for P {}
51
52/// Represents the expected type used for formatting.
53///
54/// Returned by the [`expected`] method of the [`PredicateExpected`] extension trait.
55///
56/// This type delegates the following traits:
57///
58/// - [`fmt::Debug`] to [`expect_code`];
59/// - [`fmt::Display`] to [`expect`].
60///
61/// [`expected`]: PredicateExpected::expected
62/// [`expect_code`]: Predicate::expect_code
63/// [`expect`]: Predicate::expect
64pub struct Expected<T: ?Sized, P: Predicate<T> + ?Sized> {
65    value: PhantomData<T>,
66    predicate: PhantomData<P>,
67}
68
69impl<T: ?Sized, P: Predicate<T> + ?Sized> Default for Expected<T, P> {
70    fn default() -> Self {
71        Self::new()
72    }
73}
74
75impl<T: ?Sized, P: Predicate<T> + ?Sized> Expected<T, P> {
76    /// Constructs [`Self`].
77    #[must_use]
78    pub const fn new() -> Self {
79        Self {
80            value: PhantomData,
81            predicate: PhantomData,
82        }
83    }
84}
85
86impl<T: ?Sized, P: Predicate<T> + ?Sized> fmt::Debug for Expected<T, P> {
87    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
88        P::expect_code(formatter)
89    }
90}
91
92impl<T: ?Sized, P: Predicate<T> + ?Sized> fmt::Display for Expected<T, P> {
93    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
94        P::expect(formatter)
95    }
96}
97
98/// Extends any type `T` to check whether values satisfy given [`Predicate<T>`].
99pub trait Check {
100    /// Checks whether the [`Self`] value satisfies the given predicate.
101    ///
102    /// This method calls [`P::check`] in its implementation.
103    ///
104    /// [`P::check`]: Predicate::check
105    fn satisfies<P: Predicate<Self> + ?Sized>(&self) -> bool {
106        P::check(self)
107    }
108}
109
110impl<T: ?Sized> Check for T {}