1use crate::assertions::{
4 AssertDecimalNumber, AssertInfinity, AssertNotANumber, AssertNumericIdentity, AssertSignum,
5};
6use crate::colored::{mark_missing, mark_missing_string, mark_unexpected};
7use crate::expectations::{
8 has_precision_of, has_scale_of, is_a_number, is_finite, is_infinite, is_integer, is_negative,
9 is_one, is_positive, is_zero, not, HasPrecisionOf, HasScaleOf, IsANumber, IsFinite, IsInfinite,
10 IsInteger, IsNegative, IsOne, IsPositive, IsZero,
11};
12use crate::properties::{
13 AdditiveIdentityProperty, DecimalProperties, InfinityProperty, IsNanProperty,
14 MultiplicativeIdentityProperty, SignumProperty,
15};
16use crate::spec::{DiffFormat, Expectation, Expression, FailingStrategy, Invertible, Spec};
17use crate::std::fmt::Debug;
18use crate::std::format;
19use crate::std::string::String;
20
21impl<S, R> AssertSignum for Spec<'_, S, R>
22where
23 S: SignumProperty + Debug,
24 R: FailingStrategy,
25{
26 fn is_negative(self) -> Self {
27 self.expecting(is_negative())
28 }
29
30 fn is_not_negative(self) -> Self {
31 self.expecting(not(is_negative()))
32 }
33
34 fn is_positive(self) -> Self {
35 self.expecting(is_positive())
36 }
37
38 fn is_not_positive(self) -> Self {
39 self.expecting(not(is_positive()))
40 }
41}
42
43impl<S> Expectation<S> for IsNegative
44where
45 S: SignumProperty + Debug,
46{
47 fn test(&mut self, subject: &S) -> bool {
48 subject.is_negative_property()
49 }
50
51 fn message(
52 &self,
53 expression: &Expression<'_>,
54 actual: &S,
55 inverted: bool,
56 format: &DiffFormat,
57 ) -> String {
58 let (not, expected) = if inverted {
59 ("not ", ">= 0")
60 } else {
61 ("", "< 0")
62 };
63 let marked_actual = mark_unexpected(actual, format);
64 let marked_expected = mark_missing_string(expected, format);
65 format!("expected {expression} to be {not}negative\n but was: {marked_actual}\n expected: {marked_expected}")
66 }
67}
68
69impl Invertible for IsNegative {}
70
71impl<S> Expectation<S> for IsPositive
72where
73 S: SignumProperty + Debug,
74{
75 fn test(&mut self, subject: &S) -> bool {
76 subject.is_positive_property()
77 }
78
79 fn message(
80 &self,
81 expression: &Expression<'_>,
82 actual: &S,
83 inverted: bool,
84 format: &DiffFormat,
85 ) -> String {
86 let (not, expected) = if inverted {
87 ("not ", "<= 0")
88 } else {
89 ("", "> 0")
90 };
91 let marked_actual = mark_unexpected(actual, format);
92 let marked_expected = mark_missing_string(expected, format);
93 format!("expected {expression} to be {not}positive\n but was: {marked_actual}\n expected: {marked_expected}")
94 }
95}
96
97impl Invertible for IsPositive {}
98
99impl<S, R> AssertNumericIdentity for Spec<'_, S, R>
100where
101 S: AdditiveIdentityProperty + MultiplicativeIdentityProperty + PartialEq + Debug,
102 R: FailingStrategy,
103{
104 fn is_zero(self) -> Self {
105 self.expecting(is_zero())
106 }
107
108 fn is_one(self) -> Self {
109 self.expecting(is_one())
110 }
111}
112
113impl<S> Expectation<S> for IsZero
114where
115 S: AdditiveIdentityProperty + PartialEq + Debug,
116{
117 fn test(&mut self, subject: &S) -> bool {
118 *subject == <S as AdditiveIdentityProperty>::additive_identity()
119 }
120
121 fn message(
122 &self,
123 expression: &Expression<'_>,
124 actual: &S,
125 inverted: bool,
126 format: &DiffFormat,
127 ) -> String {
128 let not = if inverted { "not " } else { "" };
129 let marked_actual = mark_unexpected(&actual, format);
130 let marked_expected = mark_missing(&S::additive_identity(), format);
131 format!("expected {expression} to be {not}zero\n but was: {marked_actual}\n expected: {not}{marked_expected}")
132 }
133}
134
135impl Invertible for IsZero {}
136
137impl<S> Expectation<S> for IsOne
138where
139 S: MultiplicativeIdentityProperty + PartialEq + Debug,
140{
141 fn test(&mut self, subject: &S) -> bool {
142 *subject == <S as MultiplicativeIdentityProperty>::multiplicative_identity()
143 }
144
145 fn message(
146 &self,
147 expression: &Expression<'_>,
148 actual: &S,
149 inverted: bool,
150 format: &DiffFormat,
151 ) -> String {
152 let not = if inverted { "not " } else { "" };
153 let marked_actual = mark_unexpected(actual, format);
154 let marked_expected = mark_missing(&S::multiplicative_identity(), format);
155 format!("expected {expression} to be {not}one\n but was: {marked_actual}\n expected: {not}{marked_expected}")
156 }
157}
158
159impl Invertible for IsOne {}
160
161impl<S, R> AssertInfinity for Spec<'_, S, R>
162where
163 S: InfinityProperty + Debug,
164 R: FailingStrategy,
165{
166 fn is_infinite(self) -> Self {
167 self.expecting(is_infinite())
168 }
169
170 fn is_finite(self) -> Self {
171 self.expecting(is_finite())
172 }
173}
174
175impl<S> Expectation<S> for IsFinite
176where
177 S: InfinityProperty + Debug,
178{
179 fn test(&mut self, subject: &S) -> bool {
180 subject.is_finite_property()
181 }
182
183 fn message(
184 &self,
185 expression: &Expression<'_>,
186 actual: &S,
187 inverted: bool,
188 format: &DiffFormat,
189 ) -> String {
190 let (not, expected) = if inverted {
191 ("not ", "a non-finite number")
192 } else {
193 ("", "a finite number")
194 };
195 let marked_actual = mark_unexpected(actual, format);
196 let marked_expected = mark_missing_string(expected, format);
197 format!("expected {expression} to be {not}finite\n but was: {marked_actual}\n expected: {marked_expected}")
198 }
199}
200
201impl Invertible for IsFinite {}
202
203impl<S> Expectation<S> for IsInfinite
204where
205 S: InfinityProperty + Debug,
206{
207 fn test(&mut self, subject: &S) -> bool {
208 subject.is_infinite_property()
209 }
210
211 fn message(
212 &self,
213 expression: &Expression<'_>,
214 actual: &S,
215 inverted: bool,
216 format: &DiffFormat,
217 ) -> String {
218 let (not, expected) = if inverted {
219 ("not ", "a non-infinite number")
220 } else {
221 ("", "an infinite number")
222 };
223 let marked_actual = mark_unexpected(actual, format);
224 let marked_expected = mark_missing_string(expected, format);
225 format!("expected {expression} to be {not}infinite\n but was: {marked_actual}\n expected: {marked_expected}")
226 }
227}
228
229impl Invertible for IsInfinite {}
230
231impl<S, R> AssertNotANumber for Spec<'_, S, R>
232where
233 S: IsNanProperty + Debug,
234 R: FailingStrategy,
235{
236 fn is_not_a_number(self) -> Self {
237 self.expecting(not(is_a_number()))
238 }
239
240 fn is_a_number(self) -> Self {
241 self.expecting(is_a_number())
242 }
243}
244
245impl<S> Expectation<S> for IsANumber
246where
247 S: IsNanProperty + Debug,
248{
249 fn test(&mut self, subject: &S) -> bool {
250 !subject.is_nan_property()
251 }
252
253 fn message(
254 &self,
255 expression: &Expression<'_>,
256 actual: &S,
257 inverted: bool,
258 format: &DiffFormat,
259 ) -> String {
260 let (not, expected) = if inverted {
261 ("not ", "NaN")
262 } else {
263 ("", "a number")
264 };
265 let marked_actual = mark_unexpected(actual, format);
266 let marked_expected = mark_missing_string(expected, format);
267 format!("expected {expression} to be {not}a number\n but was: {marked_actual}\n expected: {marked_expected}")
268 }
269}
270
271impl Invertible for IsANumber {}
272
273impl<S, R> AssertDecimalNumber for Spec<'_, S, R>
274where
275 S: DecimalProperties + Debug,
276 R: FailingStrategy,
277{
278 fn has_scale_of(self, expected_scale: i64) -> Self {
279 self.expecting(has_scale_of(expected_scale))
280 }
281
282 fn has_precision_of(self, expected_precision: u64) -> Self {
283 self.expecting(has_precision_of(expected_precision))
284 }
285
286 fn is_integer(self) -> Self {
287 self.expecting(is_integer())
288 }
289}
290
291impl<S> Expectation<S> for HasScaleOf
292where
293 S: DecimalProperties + Debug,
294{
295 fn test(&mut self, subject: &S) -> bool {
296 subject.scale_property() == self.expected_scale
297 }
298
299 fn message(
300 &self,
301 expression: &Expression<'_>,
302 actual: &S,
303 inverted: bool,
304 format: &DiffFormat,
305 ) -> String {
306 let not = if inverted { "not " } else { "" };
307 let expected_scale = self.expected_scale;
308 let marked_actual = mark_unexpected(&actual.scale_property(), format);
309 let marked_expected = mark_missing(&expected_scale, format);
310 format!("expected {expression} to {not}have a scale of {expected_scale}\n but was: {marked_actual}\n expected: {not}{marked_expected}")
311 }
312}
313
314impl Invertible for HasScaleOf {}
315
316impl<S> Expectation<S> for HasPrecisionOf
317where
318 S: DecimalProperties + Debug,
319{
320 fn test(&mut self, subject: &S) -> bool {
321 subject.precision_property() == self.expected_precision
322 }
323
324 fn message(
325 &self,
326 expression: &Expression<'_>,
327 actual: &S,
328 inverted: bool,
329 format: &DiffFormat,
330 ) -> String {
331 let not = if inverted { "not " } else { "" };
332 let expected_precision = self.expected_precision;
333 let marked_actual = mark_unexpected(&actual.precision_property(), format);
334 let marked_expected = mark_missing(&expected_precision, format);
335 format!("expected {expression} to {not}have a precision of {expected_precision}\n but was: {marked_actual}\n expected: {not}{marked_expected}")
336 }
337}
338
339impl<S> Expectation<S> for IsInteger
340where
341 S: DecimalProperties + Debug,
342{
343 fn test(&mut self, subject: &S) -> bool {
344 subject.is_integer_property()
345 }
346
347 fn message(
348 &self,
349 expression: &Expression<'_>,
350 actual: &S,
351 inverted: bool,
352 format: &DiffFormat,
353 ) -> String {
354 let (not, expected) = if inverted {
355 ("not ", "a decimal value with non-zero fraction")
356 } else {
357 ("", "an integer value")
358 };
359 let marked_actual = mark_unexpected(&actual, format);
360 let marked_expected = mark_missing_string(expected, format);
361 format!("expected {expression} to be {not}an integer value\n but was: {marked_actual}\n expected: {marked_expected}")
362 }
363}