num_convert/
extra_traits.rs

1use crate::{FromAs, IntoAs};
2use core::ops::Rem;
3use core::ops::Div;
4
5/// A trait IntegerLen to determine the number of digits of integers.
6///
7/// # Usage
8/// Basic use of the trait.
9///
10/// ```
11/// use num_convert::IntegerLen;
12///
13/// assert_eq!(i8::MAX.len(), 3usize);
14/// assert_eq!(u128::MAX.len(), 39usize);
15/// ```
16///
17/// # Examples
18/// ```
19/// # use num_convert::IntegerLen;
20/// assert_eq!(0_i8.len(), 1_usize);
21/// assert_eq!(i128::MAX.len(), 39_usize);
22/// ```
23#[allow(clippy::len_without_is_empty)]
24pub trait IntegerLen {
25    /// Returns the number of digits for self value.
26    fn len(self) -> usize;
27}
28
29impl<T> IntegerLen for T
30where
31    T: Eq + Copy + Div<Output = T> + IntoAs<T> + FromAs<u8>,
32    u8: IntoAs<T>,
33{
34    #[inline]
35    fn len(mut self) -> usize {
36        let mut count = 0;
37        let ten = 10.into_as();
38        let zero = <T>::from_as(0);
39        while self != zero {
40            self = self / ten;
41            count += 1;
42        }
43        if count == 0 {
44            1
45        } else {
46            count
47        }
48    }
49}
50
51/// Trait for type info.
52pub trait TypeInfo {
53    /// Returns the type.
54    fn info() -> &'static str;
55}
56
57macro_rules! type_info_impls {
58    ($($type:ty, $type_str:expr);* ) => {
59        $(
60            impl TypeInfo for $type {
61                #[inline]
62                fn info() -> &'static str {
63                    $type_str
64                }
65            }
66        )*
67    }
68}
69
70type_info_impls! { i8, "i8"; i16, "i16"; i32, "i32"; i64, "i64"; isize, "isize"; i128, "i128" }
71type_info_impls! { u8, "u8"; u16, "u16"; u32, "u32"; u64, "u64"; usize, "usize"; u128, "u128" }
72
73/// Trait value type info.
74pub trait ValTypeInfo {
75    /// Returns value type info.
76    fn info(self) -> &'static str;
77}
78
79macro_rules! val_type_info_impls {
80    ($($type:ty, $type_str:expr);* ) => {
81        $(
82            impl ValTypeInfo for $type {
83                #[inline]
84                fn info(self) -> &'static str {
85                    $type_str
86                }
87            }
88        )*
89    }
90}
91
92val_type_info_impls! { i8, "i8"; i16, "i16"; i32, "i32"; i64, "i64"; isize, "isize"; i128, "i128" }
93val_type_info_impls! { u8, "u8"; u16, "u16"; u32, "u32"; u64, "u64"; usize, "usize"; u128, "u128" }
94
95impl<T> CheckRem for T
96where
97    T: Copy + Default + Rem<Output = T> + PartialEq,
98{ }
99
100/// Trait for checking the remainder.
101pub trait CheckRem: Rem<Output = Self> + PartialEq
102where
103    Self: Copy + Default,
104{
105    /// Returns true if there is no remainder.
106    ///
107    /// # Panics
108    /// If the divisor is zero.
109    ///
110    /// # Arguments
111    ///
112    /// * `n` - The divisor with which the remainder is checked.
113    ///
114    /// # Examples
115    ///
116    /// ```
117    /// use num_convert::CheckRem;
118    ///
119    /// assert_eq!(10.no_rem(2), true);
120    /// assert_eq!(10.no_rem(3), false);
121    /// ```
122    #[inline]
123    fn no_rem(&self, n: Self) -> bool {
124        *self % n == Self::default()
125    }
126
127    /// Returns true if there is a remainder.
128    ///
129    /// # Arguments
130    ///
131    /// * `n` - The divisor with which the remainder is checked.
132    ///
133    /// # Examples
134    ///
135    /// ```
136    /// use num_convert::CheckRem;
137    ///
138    /// assert_eq!(10.is_rem(2), false);
139    /// assert_eq!(10.is_rem(3), true);
140    /// ```
141    #[inline]
142    fn is_rem(&self, n: Self) -> bool {
143        *self % n != Self::default()
144    }
145}