num_convert/
convert_try_from_digits.rs1use core::ops::Rem;
2
3pub trait TryFromDigits<T> {
24 fn from_digits(n: T) -> Result<Self, <Self as TryFrom<T>>::Error>
26 where
27 Self: TryFrom<T>;
28}
29
30macro_rules! try_from_digits_impls {
31 ( $($type:ty, $trait_name:ident);* ) => {
32 $(
33 impl<T> TryFromDigits<T> for $type
34 where
35 T: Rem<T, Output = T> + $trait_name,
36 Self: TryFrom<T>,
37 {
38 #[doc = concat!("Converts ", stringify!($type), " to digit range Self.")]
39 #[inline]
40 fn from_digits(n: T) -> Result<Self, <Self as TryFrom<T>>::Error>
41 {
42 <Self as TryFrom<T>>::try_from(n % T::num())
43 }
44 }
45 )*
46 }
47}
48
49try_from_digits_impls! { i8,Thousands; u8, Thousands; i16, HundredThousands; u16, HundredThousands;
50i32, TenBillions; u32, TenBillions; i64, BigTen; u64, BigHundred; isize, BigTen; usize, BigHundred }
51
52trait Thousands {
53 fn num() -> Self;
54}
55
56macro_rules! thousands_impls {
57 ( $($type:ty),* ; $value:expr ) => {
58 $(
59 impl Thousands for $type {
60 #[inline]
61 fn num() -> Self {
62 $value
63 }
64 }
65 )*
66 }
67}
68
69thousands_impls! { i16, u16, i32, u32, i64, u64, isize, usize, i128, u128; 1000 }
70
71trait HundredThousands {
72 fn num() -> Self;
73}
74
75macro_rules! hundred_thousands_impls {
76 ( $($type:ty),* ; $value:expr ) => {
77 $(
78 impl HundredThousands for $type {
79 #[inline]
80 fn num() -> Self {
81 $value
82 }
83 }
84 )*
85 }
86}
87
88hundred_thousands_impls! { i32, u32, i64, u64, isize, usize, i128, u128; 100_000 }
89
90trait TenBillions {
91 fn num() -> Self;
92}
93
94macro_rules! ten_billions_impls {
95 ( $($type:ty),* ; $value:expr ) => {
96 $(
97 impl TenBillions for $type {
98 #[inline]
99 fn num() -> Self {
100 $value
101 }
102 }
103 )*
104 }
105}
106
107ten_billions_impls! { i64, u64, isize, usize, i128, u128; 10_000_000_000 }
108
109trait BigTen {
110 fn num() -> Self;
111}
112
113trait BigHundred {
114 fn num() -> Self;
115}
116
117macro_rules! big_impls {
118 ( $( $trait_name:ident, $type:ty, $value:expr );* ) => {
119 $(
120 impl $trait_name for $type {
121 #[inline]
122 fn num() -> Self {
123 $value
124 }
125 }
126 )*
127 }
128}
129
130big_impls! { BigTen, i128, 10_000_000_000_000_000_000; BigHundred, u128, 100_000_000_000_000_000_000 }
131big_impls! { BigTen, u128, 10_000_000_000_000_000_000; BigHundred, i128, 100_000_000_000_000_000_000 }
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136 use paste::paste;
137
138 macro_rules! try_from_digits {
139 ( $trait_name:ident; $($type:ty),* ; $value:expr ) => {
140 $( paste! {
141 #[test]
142 fn [<digit_$type _value_$value _test>]() {
143 assert_eq!(<$type as $trait_name>::num(), $value);
144 }
145
146 })*
147 }
148 }
149
150 try_from_digits! { Thousands; i16, u16, i32, u32, i64, u64, isize, usize, i128, u128; 1000 }
151 try_from_digits! { HundredThousands; i32, u32, i64, u64, isize, usize, i128, u128; 100_000 }
152 try_from_digits! { TenBillions; i64, u64, isize, usize, i128, u128; 10_000_000_000 }
153 try_from_digits! { BigTen; i128; 10_000_000_000_000_000_000 }
154 try_from_digits! { BigTen; u128; 10_000_000_000_000_000_000 }
155 try_from_digits! { BigHundred; u128; 100_000_000_000_000_000_000 }
156 try_from_digits! { BigHundred; i128; 100_000_000_000_000_000_000 }
157}