• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ISibboI / evalexpr / 11381099505

17 Oct 2024 08:20AM UTC coverage: 90.154% (-2.4%) from 92.543%
11381099505

push

github

web-flow
Make int and float types generic and change license to AGPLv3. (#171)

326 of 342 new or added lines in 13 files covered. (95.32%)

40 existing lines in 8 files now uncovered.

1346 of 1493 relevant lines covered (90.15%)

8.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.68
/src/value/numeric_types.rs
1
use std::{
2
    convert::TryInto,
3
    fmt::{Debug, Display},
4
    ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub},
5
    str::FromStr,
6
};
7

8
use crate::{EvalexprError, EvalexprResult, Value};
9

10
/// A trait to parameterise `evalexpr` with an int type and a float type.
11
///
12
/// See [`EvalexprInt`] and [`EvalexprFloat`] for the requirements on the types.
13
pub trait EvalexprNumericTypes: 'static + Sized + Debug + Clone + PartialEq {
14
    /// The integer type.
15
    #[cfg(feature = "serde")]
16
    type Int: EvalexprInt<Self> + serde::Serialize + for<'de> serde::Deserialize<'de>;
17

18
    /// The integer type.
19
    #[cfg(not(feature = "serde"))]
20
    type Int: EvalexprInt<Self>;
21

22
    /// The float type.
23
    #[cfg(feature = "serde")]
24
    type Float: EvalexprFloat<Self> + serde::Serialize + for<'de> serde::Deserialize<'de>;
25

26
    /// The float type.
27
    #[cfg(not(feature = "serde"))]
28
    type Float: EvalexprFloat<Self>;
29

30
    /// Convert an integer to a float using the `as` operator or a similar mechanic.
31
    fn int_as_float(int: &Self::Int) -> Self::Float;
32

33
    /// Convert a float to an integer using the `as` operator or a similar mechanic.
34
    fn float_as_int(float: &Self::Float) -> Self::Int;
35
}
36

37
/// An integer type that can be used by `evalexpr`.
38
pub trait EvalexprInt<NumericTypes: EvalexprNumericTypes<Int = Self>>:
39
    Clone + Debug + Display + FromStr + Eq + Ord
40
{
41
    /// The minimum value of the integer type.
42
    const MIN: Self;
43

44
    /// The maximum value of the integer type.
45
    const MAX: Self;
46

47
    /// Convert a value of type [`usize`] into `Self`.
48
    fn from_usize(int: usize) -> EvalexprResult<Self, NumericTypes>;
49

50
    /// Convert `self` into [`usize`].
51
    #[expect(clippy::wrong_self_convention)]
52
    fn into_usize(&self) -> EvalexprResult<usize, NumericTypes>;
53

54
    /// Parse `Self` from a hex string.
55
    #[expect(clippy::result_unit_err)]
56
    fn from_hex_str(literal: &str) -> Result<Self, ()>;
57

58
    /// Perform an addition operation, returning an error on overflow.
59
    fn checked_add(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes>;
60

61
    /// Perform a subtraction operation, returning an error on overflow.
62
    fn checked_sub(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes>;
63

64
    /// Perform a negation operation, returning an error on overflow.
65
    fn checked_neg(&self) -> EvalexprResult<Self, NumericTypes>;
66

67
    /// Perform a multiplication operation, returning an error on overflow.
68
    fn checked_mul(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes>;
69

70
    /// Perform a division operation, returning an error on overflow.
71
    fn checked_div(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes>;
72

73
    /// Perform a remainder operation, returning an error on overflow.
74
    fn checked_rem(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes>;
75

76
    /// Compute the absolute value, returning an error on overflow.
77
    fn abs(&self) -> EvalexprResult<Self, NumericTypes>;
78

79
    /// Perform a bitand operation.
80
    fn bitand(&self, rhs: &Self) -> Self;
81

82
    /// Perform a bitor operation.
83
    fn bitor(&self, rhs: &Self) -> Self;
84

85
    /// Perform a bitxor operation.
86
    fn bitxor(&self, rhs: &Self) -> Self;
87

88
    /// Perform a bitnot operation.
89
    fn bitnot(&self) -> Self;
90

91
    /// Perform a shl operation.
92
    fn bit_shift_left(&self, rhs: &Self) -> Self;
93

94
    /// Perform a shr operation.
95
    fn bit_shift_right(&self, rhs: &Self) -> Self;
96
}
97

98
/// A float type that can be used by `evalexpr`.
99
pub trait EvalexprFloat<NumericTypes: EvalexprNumericTypes<Float = Self>>:
100
    Clone
101
    + Debug
102
    + Display
103
    + FromStr
104
    + PartialEq
105
    + PartialOrd
106
    + Add<Output = Self>
107
    + Sub<Output = Self>
108
    + Neg<Output = Self>
109
    + Mul<Output = Self>
110
    + Div<Output = Self>
111
    + Rem<Output = Self>
112
{
113
    /// The smallest non-NaN floating point value.
114
    ///
115
    /// Typically, this is negative infinity.
116
    const MIN: Self;
117

118
    /// The largest non-NaN floating point value.
119
    ///
120
    /// Typically, this is positive infinity.
121
    const MAX: Self;
122

123
    /// Perform a power operation.
124
    fn pow(&self, exponent: &Self) -> Self;
125

126
    /// Compute the natural logarithm.
127
    fn ln(&self) -> Self;
128

129
    /// Compute the logarithm to a certain base.
130
    fn log(&self, base: &Self) -> Self;
131

132
    /// Compute the logarithm base 2.
133
    fn log2(&self) -> Self;
134

135
    /// Compute the logarithm base 10.
136
    fn log10(&self) -> Self;
137

138
    /// Exponentiate with base `e`.
139
    fn exp(&self) -> Self;
140

141
    /// Exponentiate with base 2.
142
    fn exp2(&self) -> Self;
143

144
    /// Compute the cosine.
145
    fn cos(&self) -> Self;
146

147
    /// Compute the hyperbolic cosine.
148
    fn cosh(&self) -> Self;
149

150
    /// Compute the arccosine.
151
    fn acos(&self) -> Self;
152

153
    /// Compute the hyperbolic arccosine.
154
    fn acosh(&self) -> Self;
155

156
    /// Compute the sine.
157
    fn sin(&self) -> Self;
158

159
    /// Compute the hyperbolic sine.
160
    fn sinh(&self) -> Self;
161

162
    /// Compute the arcsine.
163
    fn asin(&self) -> Self;
164

165
    /// Compute the hyperbolic arcsine.
166
    fn asinh(&self) -> Self;
167

168
    /// Compute the tangent.
169
    fn tan(&self) -> Self;
170

171
    /// Compute the hyperbolic tangent.
172
    fn tanh(&self) -> Self;
173

174
    /// Compute the arctangent.
175
    fn atan(&self) -> Self;
176

177
    /// Compute the hyperbolic arctangent.
178
    fn atanh(&self) -> Self;
179

180
    /// Compute the four quadrant arctangent.
181
    fn atan2(&self, x: &Self) -> Self;
182

183
    /// Compute the square root.
184
    fn sqrt(&self) -> Self;
185

186
    /// Compute the cubic root.
187
    fn cbrt(&self) -> Self;
188

189
    /// Compute the distance between the origin and a point (`self`, `other`) on the Euclidean plane.
190
    fn hypot(&self, other: &Self) -> Self;
191

192
    /// Compute the largest integer less than or equal to `self`.
193
    fn floor(&self) -> Self;
194

195
    /// Returns the nearest integer to `self`. If a value is half-way between two integers, round away from `0.0`.
196
    fn round(&self) -> Self;
197

198
    /// Compute the largest integer greater than or equal to `self`.
199
    fn ceil(&self) -> Self;
200

201
    /// Returns true if `self` is not a number.
202
    fn is_nan(&self) -> bool;
203

204
    /// Returns true if `self` is finite.
205
    fn is_finite(&self) -> bool;
206

207
    /// Returns true if `self` is infinite.
208
    fn is_infinite(&self) -> bool;
209

210
    /// Returns true if `self` is normal.
211
    fn is_normal(&self) -> bool;
212

213
    /// Returns the absolute value of self.
214
    fn abs(&self) -> Self;
215

216
    /// Returns the minimum of the two numbers, ignoring NaN.
217
    fn min(&self, other: &Self) -> Self;
218

219
    /// Returns the maximum of the two numbers, ignoring NaN.
220
    fn max(&self, other: &Self) -> Self;
221

222
    /// Generate a random float value between 0.0 and 1.0.
223
    ///
224
    /// If the feature `rand` is not enabled, then this method always returns [`EvalexprError::RandNotEnabled`].
225
    fn random() -> EvalexprResult<Self, NumericTypes>;
226
}
227

228
/// See [`EvalexprNumericTypes`].
229
///
230
/// This empty struct uses [`i64`] as its integer type and [`f64`] as its float type.
231
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
232
pub struct DefaultNumericTypes;
233

234
impl EvalexprNumericTypes for DefaultNumericTypes {
235
    type Int = i64;
236
    type Float = f64;
237

238
    fn int_as_float(int: &Self::Int) -> Self::Float {
10✔
239
        *int as Self::Float
10✔
240
    }
241

NEW
242
    fn float_as_int(float: &Self::Float) -> Self::Int {
×
NEW
243
        *float as Self::Int
×
244
    }
245
}
246

247
impl<NumericTypes: EvalexprNumericTypes<Int = Self>> EvalexprInt<NumericTypes> for i64 {
248
    const MIN: Self = Self::MIN;
249
    const MAX: Self = Self::MAX;
250

251
    fn from_usize(int: usize) -> EvalexprResult<Self, NumericTypes> {
1✔
252
        int.try_into()
1✔
NEW
253
            .map_err(|_| EvalexprError::IntFromUsize { usize_int: int })
×
254
    }
255

256
    fn into_usize(&self) -> EvalexprResult<usize, NumericTypes> {
1✔
257
        if *self >= 0 {
2✔
258
            (*self as u64)
1✔
259
                .try_into()
NEW
260
                .map_err(|_| EvalexprError::IntIntoUsize { int: *self })
×
261
        } else {
262
            Err(EvalexprError::IntIntoUsize { int: *self })
1✔
263
        }
264
    }
265

266
    fn from_hex_str(literal: &str) -> Result<Self, ()> {
1✔
267
        Self::from_str_radix(literal, 16).map_err(|_| ())
3✔
268
    }
269

270
    fn checked_add(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes> {
14✔
271
        let result = (*self).checked_add(*rhs);
14✔
272
        if let Some(result) = result {
29✔
273
            Ok(result)
14✔
274
        } else {
275
            Err(EvalexprError::addition_error(
2✔
276
                Value::<NumericTypes>::from_int(*self),
1✔
277
                Value::<NumericTypes>::from_int(*rhs),
1✔
278
            ))
279
        }
280
    }
281

282
    fn checked_sub(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes> {
3✔
283
        let result = (*self).checked_sub(*rhs);
3✔
284
        if let Some(result) = result {
7✔
285
            Ok(result)
3✔
286
        } else {
287
            Err(EvalexprError::subtraction_error(
2✔
288
                Value::<NumericTypes>::from_int(*self),
1✔
289
                Value::<NumericTypes>::from_int(*rhs),
1✔
290
            ))
291
        }
292
    }
293

294
    fn checked_neg(&self) -> EvalexprResult<Self, NumericTypes> {
2✔
295
        let result = (*self).checked_neg();
2✔
296
        if let Some(result) = result {
4✔
297
            Ok(result)
2✔
298
        } else {
299
            Err(EvalexprError::negation_error(
1✔
300
                Value::<NumericTypes>::from_int(*self),
1✔
301
            ))
302
        }
303
    }
304

305
    fn checked_mul(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes> {
6✔
306
        let result = (*self).checked_mul(*rhs);
6✔
307
        if let Some(result) = result {
13✔
308
            Ok(result)
6✔
309
        } else {
310
            Err(EvalexprError::multiplication_error(
2✔
311
                Value::<NumericTypes>::from_int(*self),
1✔
312
                Value::<NumericTypes>::from_int(*rhs),
1✔
313
            ))
314
        }
315
    }
316

317
    fn checked_div(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes> {
2✔
318
        let result = (*self).checked_div(*rhs);
2✔
319
        if let Some(result) = result {
5✔
320
            Ok(result)
2✔
321
        } else {
322
            Err(EvalexprError::division_error(
2✔
323
                Value::<NumericTypes>::from_int(*self),
1✔
324
                Value::<NumericTypes>::from_int(*rhs),
1✔
325
            ))
326
        }
327
    }
328

329
    fn checked_rem(&self, rhs: &Self) -> EvalexprResult<Self, NumericTypes> {
1✔
330
        let result = (*self).checked_rem(*rhs);
1✔
331
        if let Some(result) = result {
3✔
332
            Ok(result)
1✔
333
        } else {
334
            Err(EvalexprError::modulation_error(
2✔
335
                Value::<NumericTypes>::from_int(*self),
1✔
336
                Value::<NumericTypes>::from_int(*rhs),
1✔
337
            ))
338
        }
339
    }
340

341
    fn abs(&self) -> EvalexprResult<Self, NumericTypes> {
1✔
342
        Ok((*self).abs())
1✔
343
    }
344

345
    fn bitand(&self, rhs: &Self) -> Self {
1✔
346
        BitAnd::bitand(*self, *rhs)
1✔
347
    }
348

349
    fn bitor(&self, rhs: &Self) -> Self {
1✔
350
        BitOr::bitor(*self, *rhs)
1✔
351
    }
352

353
    fn bitxor(&self, rhs: &Self) -> Self {
1✔
354
        BitXor::bitxor(*self, *rhs)
1✔
355
    }
356

357
    fn bitnot(&self) -> Self {
1✔
358
        Not::not(*self)
1✔
359
    }
360

361
    fn bit_shift_left(&self, rhs: &Self) -> Self {
1✔
362
        Shl::shl(*self, *rhs)
1✔
363
    }
364

365
    fn bit_shift_right(&self, rhs: &Self) -> Self {
1✔
366
        Shr::shr(*self, *rhs)
1✔
367
    }
368
}
369

370
impl<NumericTypes: EvalexprNumericTypes<Float = Self>> EvalexprFloat<NumericTypes> for f64 {
371
    const MIN: Self = Self::NEG_INFINITY;
372
    const MAX: Self = Self::INFINITY;
373

374
    fn pow(&self, exponent: &Self) -> Self {
3✔
375
        (*self).powf(*exponent)
3✔
376
    }
377

378
    fn ln(&self) -> Self {
1✔
379
        (*self).ln()
1✔
380
    }
381

382
    fn log(&self, base: &Self) -> Self {
1✔
383
        (*self).log(*base)
1✔
384
    }
385

386
    fn log2(&self) -> Self {
1✔
387
        (*self).log2()
1✔
388
    }
389

390
    fn log10(&self) -> Self {
1✔
391
        (*self).log10()
1✔
392
    }
393

394
    fn exp(&self) -> Self {
1✔
395
        (*self).exp()
1✔
396
    }
397

398
    fn exp2(&self) -> Self {
1✔
399
        (*self).exp2()
1✔
400
    }
401

402
    fn cos(&self) -> Self {
1✔
403
        (*self).cos()
1✔
404
    }
405

406
    fn cosh(&self) -> Self {
1✔
407
        (*self).cosh()
1✔
408
    }
409

410
    fn acos(&self) -> Self {
1✔
411
        (*self).acos()
1✔
412
    }
413

414
    fn acosh(&self) -> Self {
1✔
415
        (*self).acosh()
1✔
416
    }
417

418
    fn sin(&self) -> Self {
1✔
419
        (*self).sin()
1✔
420
    }
421

422
    fn sinh(&self) -> Self {
1✔
423
        (*self).sinh()
1✔
424
    }
425

426
    fn asin(&self) -> Self {
1✔
427
        (*self).asin()
1✔
428
    }
429

430
    fn asinh(&self) -> Self {
1✔
431
        (*self).asinh()
1✔
432
    }
433

434
    fn tan(&self) -> Self {
1✔
435
        (*self).tan()
1✔
436
    }
437

438
    fn tanh(&self) -> Self {
1✔
439
        (*self).tanh()
1✔
440
    }
441

442
    fn atan(&self) -> Self {
1✔
443
        (*self).atan()
1✔
444
    }
445

446
    fn atanh(&self) -> Self {
1✔
447
        (*self).atanh()
1✔
448
    }
449

450
    fn atan2(&self, x: &Self) -> Self {
1✔
451
        (*self).atan2(*x)
1✔
452
    }
453

454
    fn sqrt(&self) -> Self {
1✔
455
        (*self).sqrt()
1✔
456
    }
457

458
    fn cbrt(&self) -> Self {
1✔
459
        (*self).cbrt()
1✔
460
    }
461

462
    fn hypot(&self, other: &Self) -> Self {
1✔
463
        (*self).hypot(*other)
1✔
464
    }
465

466
    fn floor(&self) -> Self {
1✔
467
        (*self).floor()
1✔
468
    }
469

470
    fn round(&self) -> Self {
1✔
471
        (*self).round()
1✔
472
    }
473

474
    fn ceil(&self) -> Self {
1✔
475
        (*self).ceil()
1✔
476
    }
477

478
    fn is_nan(&self) -> bool {
1✔
479
        (*self).is_nan()
1✔
480
    }
481

482
    fn is_finite(&self) -> bool {
1✔
483
        (*self).is_finite()
1✔
484
    }
485

486
    fn is_infinite(&self) -> bool {
3✔
487
        (*self).is_infinite()
3✔
488
    }
489

490
    fn is_normal(&self) -> bool {
1✔
491
        (*self).is_normal()
1✔
492
    }
493

494
    fn abs(&self) -> Self {
1✔
495
        (*self).abs()
1✔
496
    }
497

498
    fn min(&self, other: &Self) -> Self {
1✔
499
        (*self).min(*other)
1✔
500
    }
501

502
    fn max(&self, other: &Self) -> Self {
1✔
503
        (*self).max(*other)
1✔
504
    }
505

506
    fn random() -> EvalexprResult<Self, NumericTypes> {
1✔
507
        #[cfg(feature = "rand")]
508
        let result = Ok(rand::random());
1✔
509

510
        #[cfg(not(feature = "rand"))]
NEW
511
        let result = Err(EvalexprError::RandNotEnabled);
×
512

NEW
513
        result
×
514
    }
515
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc