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 {}