#zero #generic #generics

zero-one

Zero and One ZSTs for use with generic code

1 unstable release

0.1.0 Dec 3, 2021

MIT/Apache

10KB
214 lines

const@Zero and const@One ZSTs for use with generic code.

These can be used in generic code where 0 and 1 literals don't work.

# #![allow(non_upper_case_globals)]
use zero_one::{Zero, One};

assert_eq!(u64::from(Zero), 0);
assert_eq!(i8::from(Zero), 0);
assert_eq!(u64::from(One), 1);
assert_eq!(i8::from(One), 1);

assert_eq!(Zero, 0);
assert_ne!(Zero, 1);
assert_ne!(One, 0);
assert_eq!(One, 1);

assert!(Zero < 10);
assert!(-10 < Zero);
assert!(One < 10);
assert!(-10 < One);

assert!(matches!(Zero::try_from(0_u16), Ok(Zero)));
assert!(matches!(Zero::try_from(1_i16), Err(_)));
assert!(matches!(One::try_from(0_u16), Err(_)));
assert!(matches!(One::try_from(1_i16), Ok(One)));

assert_eq!(Zero.to_string(), "0");
assert_eq!(One.to_string(), "1");

Even outside generic code, they can make it easier to use some std types:

use zero_one::{Zero, One};
use std::num::*;

assert_eq!(NonZeroU64::from(One), NonZeroU64::new(1).unwrap());
assert_eq!(NonZeroI8::from(One), NonZeroI8::new(1).unwrap());

They'll even work in macros that want to as cast things:

use zero_one::{Zero, One};

assert_eq!(Zero as u32, 0);
assert_eq!(Zero as i128, 0);
assert_eq!(One as u32, 1);
assert_eq!(One as i128, 1);

You can do math with them, too:

use zero_one::{Zero, One};

assert_eq!(Zero + 5, 5);
assert_eq!(Zero | 5, 5);
assert_eq!(One * 5, 5);
assert_eq!(One + 5, 6);

assert_eq!(Zero % One, Zero);
assert_eq!(One - Zero, One);
assert_eq!(Zero * 5, Zero);
assert_eq!(Zero & 5, Zero);

assert_eq!(10 + One, 11);
assert_eq!(10 + Zero, 10);

No runtime deps