Skip to content

Commit fbdc29a

Browse files
authored
Merge pull request #337 from dsemi/master
Implement Zero, One, and Num for core::num::Saturating<T>
2 parents e8c1926 + f43cabb commit fbdc29a

File tree

6 files changed

+123
-3
lines changed

6 files changed

+123
-3
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ jobs:
1111
rust: [
1212
1.60.0, # MSRV
1313
1.62.0, # has_total_cmp
14+
1.74.0, # has_num_saturating
1415
stable,
1516
beta,
1617
nightly,

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ std = []
3131
i128 = []
3232

3333
[build-dependencies]
34-
autocfg = "1"
34+
autocfg = "1.2"

build.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
fn main() {
2-
let ac = autocfg::new();
2+
let mut ac = autocfg::new();
3+
ac.set_no_std(true);
34

45
ac.emit_expression_cfg("1f64.total_cmp(&2f64)", "has_total_cmp"); // 1.62
6+
ac.emit_path_cfg("core::num::Saturating", "has_num_saturating"); // 1.74
57

68
autocfg::rerun_path("build.rs");
79
}

ci/rustup.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
set -ex
66

77
ci=$(dirname $0)
8-
for version in 1.60.0 1.62.0 stable beta nightly; do
8+
for version in 1.60.0 1.62.0 1.74.0 stable beta nightly; do
99
rustup run "$version" "$ci/test_full.sh"
1010
done

src/identities.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use core::num::Wrapping;
22
use core::ops::{Add, Mul};
33

4+
#[cfg(has_num_saturating)]
5+
use core::num::Saturating;
6+
47
/// Defines an additive identity element for `Self`.
58
///
69
/// # Laws
@@ -95,6 +98,32 @@ where
9598
const ZERO: Self = Wrapping(T::ZERO);
9699
}
97100

101+
#[cfg(has_num_saturating)]
102+
impl<T: Zero> Zero for Saturating<T>
103+
where
104+
Saturating<T>: Add<Output = Saturating<T>>,
105+
{
106+
fn is_zero(&self) -> bool {
107+
self.0.is_zero()
108+
}
109+
110+
fn set_zero(&mut self) {
111+
self.0.set_zero();
112+
}
113+
114+
fn zero() -> Self {
115+
Saturating(T::zero())
116+
}
117+
}
118+
119+
#[cfg(has_num_saturating)]
120+
impl<T: ConstZero> ConstZero for Saturating<T>
121+
where
122+
Saturating<T>: Add<Output = Saturating<T>>,
123+
{
124+
const ZERO: Self = Saturating(T::ZERO);
125+
}
126+
98127
/// Defines a multiplicative identity element for `Self`.
99128
///
100129
/// # Laws
@@ -196,6 +225,28 @@ where
196225
const ONE: Self = Wrapping(T::ONE);
197226
}
198227

228+
#[cfg(has_num_saturating)]
229+
impl<T: One> One for Saturating<T>
230+
where
231+
Saturating<T>: Mul<Output = Saturating<T>>,
232+
{
233+
fn set_one(&mut self) {
234+
self.0.set_one();
235+
}
236+
237+
fn one() -> Self {
238+
Saturating(T::one())
239+
}
240+
}
241+
242+
#[cfg(has_num_saturating)]
243+
impl<T: ConstOne> ConstOne for Saturating<T>
244+
where
245+
Saturating<T>: Mul<Output = Saturating<T>>,
246+
{
247+
const ONE: Self = Saturating(T::ONE);
248+
}
249+
199250
// Some helper functions provided for backwards compatibility.
200251

201252
/// Returns the additive identity, `0`.
@@ -236,3 +287,33 @@ fn wrapping_is_one() {
236287
fn require_one<T: One>(_: &T) {}
237288
require_one(&Wrapping(42));
238289
}
290+
291+
#[test]
292+
#[cfg(has_num_saturating)]
293+
fn saturating_identities() {
294+
macro_rules! test_saturating_identities {
295+
($($t:ty)+) => {
296+
$(
297+
assert_eq!(zero::<$t>(), zero::<Saturating<$t>>().0);
298+
assert_eq!(one::<$t>(), one::<Saturating<$t>>().0);
299+
assert_eq!((0 as $t).is_zero(), Saturating(0 as $t).is_zero());
300+
assert_eq!((1 as $t).is_zero(), Saturating(1 as $t).is_zero());
301+
)+
302+
};
303+
}
304+
305+
test_saturating_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64);
306+
}
307+
308+
#[test]
309+
#[cfg(has_num_saturating)]
310+
fn saturating_is_zero() {
311+
fn require_zero<T: Zero>(_: &T) {}
312+
require_zero(&Saturating(42));
313+
}
314+
#[test]
315+
#[cfg(has_num_saturating)]
316+
fn saturating_is_one() {
317+
fn require_one<T: One>(_: &T) {}
318+
require_one(&Saturating(42));
319+
}

src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ where
184184
}
185185
}
186186

187+
#[cfg(has_num_saturating)]
188+
impl<T: Num> Num for core::num::Saturating<T>
189+
where
190+
core::num::Saturating<T>: NumOps,
191+
{
192+
type FromStrRadixErr = T::FromStrRadixErr;
193+
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
194+
T::from_str_radix(str, radix).map(core::num::Saturating)
195+
}
196+
}
197+
187198
#[derive(Debug)]
188199
pub enum FloatErrorKind {
189200
Empty,
@@ -570,6 +581,31 @@ fn wrapping_from_str_radix() {
570581
test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
571582
}
572583

584+
#[test]
585+
#[cfg(has_num_saturating)]
586+
fn saturating_is_num() {
587+
fn require_num<T: Num>(_: &T) {}
588+
require_num(&core::num::Saturating(42_u32));
589+
require_num(&core::num::Saturating(-42));
590+
}
591+
592+
#[test]
593+
#[cfg(has_num_saturating)]
594+
fn saturating_from_str_radix() {
595+
macro_rules! test_saturating_from_str_radix {
596+
($($t:ty)+) => {
597+
$(
598+
for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] {
599+
let w = core::num::Saturating::<$t>::from_str_radix(s, r).map(|w| w.0);
600+
assert_eq!(w, <$t as Num>::from_str_radix(s, r));
601+
}
602+
)+
603+
};
604+
}
605+
606+
test_saturating_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
607+
}
608+
573609
#[test]
574610
fn check_num_ops() {
575611
fn compute<T: Num + Copy>(x: T, y: T) -> T {

0 commit comments

Comments
 (0)