Skip to main content

asserting/
properties.rs

1//! Definitions of "properties" that are used by implementations of certain
2//! assertions.
3//!
4//! A property can be some kind of information about a type's value or a certain
5//! behavior of the type. A property is defined by a trait. Each trait defines
6//! one property. Assertions around a specific property can be implemented once
7//! for all types that implement the related property trait.
8//!
9//! Property traits that define access to a specific kind of information of a
10//! type's value define an accessor method to query this information.
11//!
12//! For example, the trait [`LengthProperty`] defines that all implementing
13//! types have a length. The trait defines the accessor method `length_property`
14//! to query the length of a value of this type. For all types that implement
15//! the [`LengthProperty`] trait, the assertions around a type's length defined
16//! by [`AssertHasLength`](crate::assertions::AssertHasLength) trait can be
17//! used.
18//!
19//! Property traits that define a certain behavior of a type are often marker
20//! traits.
21//!
22//! An example for a behavior property is the [`DefinedOrderProperty`] trait. It
23//! specifies that a collection's iterator yields the items in a well-defined
24//! order.
25
26use crate::std::iter::Iterator;
27
28/// The "empty" property of a collection-like type.
29///
30/// This property is used by the implementation of the
31/// [`AsssertEmptiness`](crate::assertions::AssertEmptiness) assertions.
32pub trait IsEmptyProperty {
33    /// Returns whether the collection-like value is empty.
34    fn is_empty_property(&self) -> bool;
35}
36
37impl<T> IsEmptyProperty for &T
38where
39    T: IsEmptyProperty + ?Sized,
40{
41    fn is_empty_property(&self) -> bool {
42        <T as IsEmptyProperty>::is_empty_property(self)
43    }
44}
45
46impl<T> IsEmptyProperty for &mut T
47where
48    T: IsEmptyProperty + ?Sized,
49{
50    fn is_empty_property(&self) -> bool {
51        <T as IsEmptyProperty>::is_empty_property(self)
52    }
53}
54
55/// The length property of a collection-like type.
56///
57/// Collection-like types are, for example, `Vec`, slice, array, `HashSet`,
58/// `HashMap` and strings.
59///
60/// This property is used by the implementation of the
61/// [`AssertHasLength`](crate::assertions::AssertHasLength) assertion.
62pub trait LengthProperty {
63    /// Returns the length of a collection-like value.
64    fn length_property(&self) -> usize;
65}
66
67impl<T> LengthProperty for &T
68where
69    T: LengthProperty + ?Sized,
70{
71    fn length_property(&self) -> usize {
72        <T as LengthProperty>::length_property(self)
73    }
74}
75
76impl<T> LengthProperty for &mut T
77where
78    T: LengthProperty + ?Sized,
79{
80    fn length_property(&self) -> usize {
81        <T as LengthProperty>::length_property(self)
82    }
83}
84
85/// Marker trait to specify whether a collection or iterator iterates over its
86/// elements in a well-defined order.
87pub trait DefinedOrderProperty {}
88
89impl<C> DefinedOrderProperty for &C where C: DefinedOrderProperty + ?Sized {}
90impl<C> DefinedOrderProperty for &mut C where C: DefinedOrderProperty + ?Sized {}
91
92/// Property for types that contain characters.
93pub trait CharCountProperty {
94    /// Returns the number of characters contained in this type.
95    fn char_count_property(&self) -> usize;
96}
97
98impl<T> CharCountProperty for &T
99where
100    T: CharCountProperty + ?Sized,
101{
102    fn char_count_property(&self) -> usize {
103        <T as CharCountProperty>::char_count_property(self)
104    }
105}
106
107impl<T> CharCountProperty for &mut T
108where
109    T: CharCountProperty + ?Sized,
110{
111    fn char_count_property(&self) -> usize {
112        <T as CharCountProperty>::char_count_property(self)
113    }
114}
115
116/// The additive identity property of a numeric type.
117pub trait AdditiveIdentityProperty {
118    /// The additive identity (zero).
119    fn additive_identity() -> Self;
120}
121
122/// The multiplicative identity property of a numeric type.
123pub trait MultiplicativeIdentityProperty {
124    /// The multiplicative identity (one).
125    fn multiplicative_identity() -> Self;
126}
127
128/// A property of numeric types that can have negative and positive values.
129pub trait SignumProperty {
130    /// Returns whether this value is negative.
131    fn is_negative_property(&self) -> bool;
132
133    /// Returns whether this value is positive.
134    fn is_positive_property(&self) -> bool;
135}
136
137impl<T> SignumProperty for &T
138where
139    T: SignumProperty + ?Sized,
140{
141    fn is_negative_property(&self) -> bool {
142        <T as SignumProperty>::is_negative_property(self)
143    }
144
145    fn is_positive_property(&self) -> bool {
146        <T as SignumProperty>::is_positive_property(self)
147    }
148}
149
150impl<T> SignumProperty for &mut T
151where
152    T: SignumProperty + ?Sized,
153{
154    fn is_negative_property(&self) -> bool {
155        <T as SignumProperty>::is_negative_property(self)
156    }
157
158    fn is_positive_property(&self) -> bool {
159        <T as SignumProperty>::is_positive_property(self)
160    }
161}
162
163/// A property of floating point numbers that may have infinite or finite
164/// values.
165pub trait InfinityProperty {
166    /// Returns whether this value is infinite.
167    fn is_infinite_property(&self) -> bool;
168
169    /// Returns whether this value is finite.
170    fn is_finite_property(&self) -> bool;
171}
172
173impl<T> InfinityProperty for &T
174where
175    T: InfinityProperty + ?Sized,
176{
177    fn is_infinite_property(&self) -> bool {
178        <T as InfinityProperty>::is_infinite_property(self)
179    }
180
181    fn is_finite_property(&self) -> bool {
182        <T as InfinityProperty>::is_finite_property(self)
183    }
184}
185
186impl<T> InfinityProperty for &mut T
187where
188    T: InfinityProperty + ?Sized,
189{
190    fn is_infinite_property(&self) -> bool {
191        <T as InfinityProperty>::is_infinite_property(self)
192    }
193
194    fn is_finite_property(&self) -> bool {
195        <T as InfinityProperty>::is_finite_property(self)
196    }
197}
198
199/// The not-a-number property of floating point numbers.
200pub trait IsNanProperty {
201    /// Returns whether this value is not a number.
202    fn is_nan_property(&self) -> bool;
203}
204
205impl<T> IsNanProperty for &T
206where
207    T: IsNanProperty + ?Sized,
208{
209    fn is_nan_property(&self) -> bool {
210        <T as IsNanProperty>::is_nan_property(self)
211    }
212}
213
214impl<T> IsNanProperty for &mut T
215where
216    T: IsNanProperty + ?Sized,
217{
218    fn is_nan_property(&self) -> bool {
219        <T as IsNanProperty>::is_nan_property(self)
220    }
221}
222
223/// Properties of a decimal number.
224pub trait DecimalProperties {
225    /// Returns the precision of this decimal number.
226    ///
227    /// The precision is the total number of digits in the non-scaled integer
228    /// representation of a decimal number.
229    fn precision_property(&self) -> u64;
230
231    /// Returns the scale of this decimal number.
232    fn scale_property(&self) -> i64;
233
234    /// Returns whether this decimal number has no fractional digits
235    /// (is equivalent to an integer).
236    fn is_integer_property(&self) -> bool;
237}
238
239impl<T> DecimalProperties for &T
240where
241    T: DecimalProperties + ?Sized,
242{
243    fn precision_property(&self) -> u64 {
244        <T as DecimalProperties>::precision_property(self)
245    }
246
247    fn scale_property(&self) -> i64 {
248        <T as DecimalProperties>::scale_property(self)
249    }
250
251    fn is_integer_property(&self) -> bool {
252        <T as DecimalProperties>::is_integer_property(self)
253    }
254}
255
256impl<T> DecimalProperties for &mut T
257where
258    T: DecimalProperties + ?Sized,
259{
260    fn precision_property(&self) -> u64 {
261        <T as DecimalProperties>::precision_property(self)
262    }
263
264    fn scale_property(&self) -> i64 {
265        <T as DecimalProperties>::scale_property(self)
266    }
267
268    fn is_integer_property(&self) -> bool {
269        <T as DecimalProperties>::is_integer_property(self)
270    }
271}
272
273/// The properties of a map-like type.
274pub trait MapProperties {
275    /// The type of the keys in this map.
276    type Key;
277
278    /// The type of the values in this map.
279    type Value;
280
281    /// Returns an iterator over the keys in this map.
282    fn keys_property(&self) -> impl Iterator<Item = &Self::Key>;
283
284    /// Returns an iterator over the values in this map.
285    fn values_property(&self) -> impl Iterator<Item = &Self::Value>;
286
287    /// Returns an iterator over the key/value-pairs in this map.
288    fn entries_property(&self) -> impl Iterator<Item = (&Self::Key, &Self::Value)>;
289}