| //@ run-pass | |
| #![feature(step_trait)] | |
| #![feature(ascii_char)] | |
| use std::iter::Step; | |
| use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; | |
| use std::ascii::Char as AsciiChar; | |
| use std::net::{Ipv4Addr, Ipv6Addr}; | |
| // Pick various step sizes to exercise different overflow cases. | |
| #[rustfmt::skip] | |
| const STEPS: &[usize] = match usize::BITS { | |
| 64 => &[ | |
| 1, 2, 5, 13, 29, 61, 127, 128, 255, 256, 511, 512, | |
| 1087, 4079, 17919, 32767, 32768, 65535, 65536, | |
| (1 << 17) - 1, 1 << 17, (1 << 31) - 1, 1 << 31, | |
| (1 << 32) - 1, 1 << 32, (1 << 63) - 1, 1 << 63, | |
| usize::MAX, | |
| ], | |
| 32 => &[ | |
| 1, 2, 5, 13, 29, 61, 127, 128, 255, 256, 511, 512, | |
| 1087, 4079, 17919, 32767, 32768, 65535, 65536, | |
| (1 << 17) - 1, 1 << 17, (1 << 31) - 1, 1 << 31, | |
| usize::MAX, | |
| ], | |
| 16 => &[ | |
| 1, 2, 5, 13, 29, 61, 127, 128, 255, 256, 511, 512, | |
| 1087, 4079, 17919, 32767, 32768, usize::MAX | |
| ], | |
| _ => &[ | |
| 1, 2, 5, 13, 29, 61, 127, 128, usize::MAX | |
| ], | |
| }; | |
| fn main() { | |
| // Exhaustively test the smaller integers | |
| for &step_size in STEPS { | |
| let mut n = u8::MIN; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add(step_size as u8), true) | |
| ); | |
| let mut n = u8::MAX; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub(step_size as u8), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = i8::MIN; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add_unsigned(step_size as u8), true) | |
| ); | |
| let mut n = i8::MAX; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub_unsigned(step_size as u8), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = u16::MIN; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add(step_size as u16), true) | |
| ); | |
| let mut n = u16::MAX; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub(step_size as u16), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = i16::MIN; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add_unsigned(step_size as u16), true) | |
| ); | |
| let mut n = i16::MAX; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub_unsigned(step_size as u16), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = NonZeroU8::MIN; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!(Step::forward_overflowing(n, step_size), (NonZeroU8::MAX, true)); | |
| let mut n = NonZeroU8::MAX; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!(Step::backward_overflowing(n, step_size), (NonZeroU8::MIN, true)); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = NonZeroU16::MIN; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!(Step::forward_overflowing(n, step_size), (NonZeroU16::MAX, true)); | |
| let mut n = NonZeroU16::MAX; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!(Step::backward_overflowing(n, step_size), (NonZeroU16::MIN, true)); | |
| } | |
| // Test larger integers starting at MAX-2^16 and MIN+2^16 | |
| for &step_size in STEPS { | |
| let mut n = u32::MAX - (1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add(step_size as u32), true) | |
| ); | |
| let mut n = u32::MIN + (1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub(step_size as u32), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = i32::MAX - (1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add_unsigned(step_size as u32), true) | |
| ); | |
| let mut n = i32::MIN + (1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub_unsigned(step_size as u32), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = u64::MAX - (1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add(step_size as u64), true) | |
| ); | |
| let mut n = u64::MIN + (1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub(step_size as u64), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = i64::MAX - (1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add_unsigned(step_size as u64), true) | |
| ); | |
| let mut n = i64::MIN + (1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub_unsigned(step_size as u64), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = u128::MAX - (1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add(step_size as u128), true) | |
| ); | |
| let mut n = u128::MIN + (1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub(step_size as u128), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = i128::MAX - (1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (n.wrapping_add_unsigned(step_size as u128), true) | |
| ); | |
| let mut n = i128::MIN + (1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (n.wrapping_sub_unsigned(step_size as u128), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = Step::backward(NonZeroU32::MAX, 1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!(Step::forward_overflowing(n, step_size), (NonZeroU32::MAX, true)); | |
| let mut n = Step::forward(NonZeroU32::MIN, 1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!(Step::backward_overflowing(n, step_size), (NonZeroU32::MIN, true)); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = Step::backward(NonZeroU64::MAX, 1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!(Step::forward_overflowing(n, step_size), (NonZeroU64::MAX, true)); | |
| let mut n = Step::forward(NonZeroU64::MIN, 1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!(Step::backward_overflowing(n, step_size), (NonZeroU64::MIN, true)); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = if usize::BITS > 16 { | |
| usize::MAX - (1 << 16) | |
| } else { | |
| usize::MIN | |
| }; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!(Step::forward_overflowing(n, step_size), (n.wrapping_add(step_size), true)); | |
| let mut n = if usize::BITS > 16 { | |
| usize::MIN + (1 << 16) | |
| } else { | |
| usize::MAX | |
| }; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!(Step::backward_overflowing(n, step_size), (n.wrapping_sub(step_size), true)); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = if usize::BITS > 16 { | |
| Step::backward(NonZeroUsize::MAX, 1 << 16) | |
| } else { | |
| NonZeroUsize::MIN | |
| }; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!(Step::forward_overflowing(n, step_size), (NonZeroUsize::MAX, true)); | |
| let mut n = if usize::BITS > 16 { | |
| Step::forward(NonZeroUsize::MIN, 1 << 16) | |
| } else { | |
| NonZeroUsize::MAX | |
| }; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!(Step::backward_overflowing(n, step_size), (NonZeroUsize::MIN, true)); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = Step::backward(char::MAX, 1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!(Step::forward_overflowing(n, step_size), (char::MAX, true)); | |
| let mut n = Step::forward(char::MIN, 1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!(Step::backward_overflowing(n, step_size), (char::MIN, true)); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = AsciiChar::MIN; | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (AsciiChar::from_u8( | |
| (n as u8).wrapping_add(step_size as u8) & (AsciiChar::MAX as u8) | |
| ).unwrap(), true) | |
| ); | |
| let mut n = AsciiChar::MAX; | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (AsciiChar::from_u8( | |
| (n as u8).wrapping_sub(step_size as u8) & (AsciiChar::MAX as u8) | |
| ).unwrap(), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = Step::backward(Ipv4Addr::from_bits(u32::MAX), 1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (Ipv4Addr::from_bits(n.to_bits().wrapping_add(step_size as u32)), true) | |
| ); | |
| let mut n = Step::forward(Ipv4Addr::from_bits(u32::MIN), 1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (Ipv4Addr::from_bits(n.to_bits().wrapping_sub(step_size as u32)), true) | |
| ); | |
| } | |
| for &step_size in STEPS { | |
| let mut n = Step::backward(Ipv6Addr::from_bits(u128::MAX), 1 << 16); | |
| while let Some(p) = Step::forward_checked(n, step_size) { | |
| assert_eq!(Step::forward_overflowing(n, step_size), (p, false)); | |
| n = p; | |
| } | |
| assert_eq!( | |
| Step::forward_overflowing(n, step_size), | |
| (Ipv6Addr::from_bits(n.to_bits().wrapping_add(step_size as u128)), true) | |
| ); | |
| let mut n = Step::forward(Ipv6Addr::from_bits(u128::MIN), 1 << 16); | |
| while let Some(m) = Step::backward_checked(n, step_size) { | |
| assert_eq!(Step::backward_overflowing(n, step_size), (m, false)); | |
| n = m; | |
| } | |
| assert_eq!( | |
| Step::backward_overflowing(n, step_size), | |
| (Ipv6Addr::from_bits(n.to_bits().wrapping_sub(step_size as u128)), true) | |
| ); | |
| } | |
| } |