az 0.3.0

Checked, overflowing and static casts
Documentation
// Copyright © 2019 Trevor Spiteri

// This library is free software: you can redistribute it and/or
// modify it under the terms of either
//
//   * the Apache License, Version 2.0 or
//   * the MIT License
//
// at your option.
//
// You should have recieved copies of the Apache License and the MIT
// License along with the library. If not, see
// <https://www.apache.org/licenses/LICENSE-2.0> and
// <https://opensource.org/licenses/MIT>.

#![allow(
    clippy::float_cmp,
    clippy::cognitive_complexity,
    clippy::type_repetition_in_bounds
)]

mod float_to_int;
mod int_to_int;
mod to_float;

use crate::{Az, CheckedAs, OverflowingAs, Round, SaturatingAs, StaticAs, WrappingAs};
use core::{
    f32, f64,
    fmt::Debug,
    ops::{Add, Neg, Not, Shl, Shr, Sub},
};

trait Int
where
    Self: Copy + Debug + Default + Ord,
    Self: Shl<usize, Output = Self> + Shr<usize, Output = Self>,
    Self: Not<Output = Self> + Add<Output = Self> + Sub<Output = Self>,
{
    #[inline]
    fn zero() -> Self {
        Self::default()
    }
    #[inline]
    fn one() -> Self {
        !(!Self::default() << 1)
    }
}

impl<I> Int for I
where
    I: Copy + Debug + Default + Ord,
    I: Shl<usize, Output = I> + Shr<usize, Output = I>,
    I: Not<Output = I> + Add<Output = I> + Sub<Output = I>,
{
}

trait Float
where
    Self: Copy + Debug + PartialOrd + From<i8>,
    Self: Neg<Output = Self> + Add<Output = Self> + Sub<Output = Self>,
{
    fn prec() -> usize;
    fn nan() -> Self;
    fn inf() -> Self;
    fn max() -> Self;
    fn int_shl(int: i8, shl: i8) -> Self;
    fn to_round(self) -> Round<Self>;
}

impl Float for f32 {
    fn prec() -> usize {
        24
    }
    fn nan() -> Self {
        f32::NAN
    }
    fn inf() -> Self {
        f32::INFINITY
    }
    fn max() -> Self {
        f32::MAX
    }
    fn int_shl(int: i8, shl: i8) -> Self {
        f32::from(int) * f32::from(shl).exp2()
    }
    fn to_round(self) -> Round<f32> {
        Round(self)
    }
}

impl Float for f64 {
    fn prec() -> usize {
        53
    }
    fn nan() -> Self {
        f64::NAN
    }
    fn inf() -> Self {
        f64::INFINITY
    }
    fn max() -> Self {
        f64::MAX
    }
    fn int_shl(int: i8, shl: i8) -> Self {
        f64::from(int) * f64::from(shl).exp2()
    }
    fn to_round(self) -> Round<f64> {
        Round(self)
    }
}

#[test]
fn az() {
    assert_eq!(1.az::<u8>(), 1);
    assert_eq!((-1).checked_as::<u8>(), None);
    assert_eq!(1.checked_as::<u8>(), Some(1));
    assert_eq!((-1).saturating_as::<u8>(), 0);
    assert_eq!(1000.saturating_as::<u8>(), 255);
    assert_eq!((-1).wrapping_as::<u8>(), 255);
    assert_eq!((-1).overflowing_as::<u8>(), (255, true));
    assert_eq!(1.overflowing_as::<u8>(), (1, false));
    assert_eq!(255u8.static_as::<i16>(), Some(255));
    assert_eq!(255u8.static_as::<u8>(), Some(255));
}