1use crate::{
2 ChineseNumeral, Error, LongScaleInt, MidScaleInt, MyriadScaleInt, ShortScaleInt, Sign,
3};
4
5#[cfg(feature = "bigint")]
6use crate::{LongScaleBigInt, MidScaleBigInt, MyriadScaleBigInt};
7#[cfg(feature = "bigint")]
8use num_bigint::{BigInt, BigUint};
9
10macro_rules! impl_signed_int {
11 ($($int:ident, $data:ty),+ $(,)?) => {
12 $(impl crate::Signed for $int {
13 type Data = $data;
14
15 fn sign(&self) -> Sign {
16 self.sign
17 }
18
19 fn data(&self) -> &Self::Data {
20 &self.data
21 }
22 })+
23 };
24}
25
26impl_signed_int! {ShortScaleInt, u64, MyriadScaleInt, u128, MidScaleInt, u128, LongScaleInt, u128}
27
28#[cfg(feature = "bigint")]
29impl_signed_int! {MyriadScaleBigInt, BigUint, MidScaleBigInt, BigUint, LongScaleBigInt, BigUint}
30
31macro_rules! impl_disp {
32 ($($int:ident),+ $(,)?) => {
33 $(impl std::fmt::Display for $int {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 if f.alternate() {
36 write!(f, "{}", self.to_uppercase_simp())
37 } else {
38 write!(f, "{}", self.to_lowercase_simp())
39 }
40 }
41 })+
42 };
43}
44
45impl_disp! {ShortScaleInt, MyriadScaleInt, MidScaleInt, LongScaleInt}
46
47#[cfg(feature = "bigint")]
48impl_disp! {MyriadScaleBigInt, MidScaleBigInt, LongScaleBigInt}
49
50macro_rules! impl_try_from_uint {
51 ($($u:ty),+ $(,)?) => {
52 $(impl TryFrom<$u> for ShortScaleInt {
53 type Error = Error;
54
55 fn try_from(value: $u) -> Result<Self, Self::Error> {
57 if value == 0 {
58 Ok(Self::default())
59 } else if value <= Self::MAX_ABS as $u {
60 Ok(Self {
61 sign: Sign::Pos,
62 data: value as u64,
63 })
64 } else {
65 Err(Error::ShortScaleOutOfRange(value as u128))
66 }
67 }
68 })+
69 };
70}
71
72impl_try_from_uint! {u64, u128, usize}
73
74macro_rules! impl_try_from_int {
75 ($($i:ty),+ $(,)?) => {
76 $(impl TryFrom<$i> for ShortScaleInt {
77 type Error = Error;
78
79 fn try_from(value: $i) -> Result<Self, Self::Error> {
81 if value < -(Self::MAX_ABS as $i) || value > Self::MAX_ABS as $i {
82 let abs = if value as i128 == i128::MIN {
83 (i128::MAX as u128) + 1
84 } else {
85 value.abs() as u128
86 };
87 Err(Error::ShortScaleOutOfRange(abs))
88 } else if value.is_negative() {
89 Ok(Self {
90 sign: Sign::Neg,
91 data: value.abs() as u64,
92 })
93 } else if value.is_positive() {
94 Ok(Self {
95 sign: Sign::Pos,
96 data: value as u64,
97 })
98 } else {
99 Ok(Self::default())
100 }
101 }
102 })+
103 };
104}
105
106impl_try_from_int! {i64, i128, isize}
107
108macro_rules! impl_from_int {
109 ($num:ident, $data:ty, $($pre:ty),+ $(,)?) => {
110 $(impl From<$pre> for $num {
111 fn from(value: $pre) -> Self {
112 if value == 0 {
113 Self::default()
114 } else if value < 0 {
115 let abs = if value == <$pre>::MIN {
116 (<$pre>::MAX as $data) + 1
117 } else {
118 value.abs() as $data
119 };
120 Self {
121 sign: Sign::Neg,
122 data: abs,
123 }
124 } else {
125 Self {
126 sign: Sign::Pos,
127 data: value as $data,
128 }
129 }
130 }
131 })+
132 };
133}
134
135impl_from_int! {ShortScaleInt, u64, i8, i16, i32}
136impl_from_int! {MyriadScaleInt, u128, i8, i16, i32, i64, i128, isize}
137impl_from_int! {MidScaleInt, u128, i8, i16, i32, i64, i128, isize}
138impl_from_int! {LongScaleInt, u128, i8, i16, i32, i64, i128, isize}
139
140macro_rules! impl_from_uint {
141 ($num:ident, $data:ty, $($pre:ty),+ $(,)?) => {
142 $(impl From<$pre> for $num {
143 fn from(value: $pre) -> Self {
144 if value == 0 {
145 Self::default()
146 } else {
147 Self {
148 sign: Sign::Pos,
149 data: value as $data,
150 }
151 }
152 }
153 })+
154 };
155}
156
157impl_from_uint! {ShortScaleInt, u64, u8, u16, u32}
158impl_from_uint! {MyriadScaleInt, u128, u8, u16, u32, u64, u128, usize}
159impl_from_uint! {MidScaleInt, u128, u8, u16, u32, u64, u128, usize}
160impl_from_uint! {LongScaleInt, u128, u8, u16, u32, u64, u128, usize}
161
162#[cfg(feature = "bigint")]
163macro_rules! impl_try_from_big {
164 ($($int:ty, $err:ident),+ $(,)?) => {
165 $(
166 impl TryFrom<&BigUint> for $int {
167 type Error = Error;
168
169 fn try_from(value: &BigUint) -> Result<Self, Self::Error> {
171 use num_traits::Zero;
172 if value == &BigUint::zero() {
173 Ok(Self::default())
174 } else if value <= &BigUint::from_slice(Self::MAX_ABS_ARR) {
175 Ok(Self {
176 sign: Sign::Pos,
177 data: value.to_owned(),
178 })
179 } else {
180 Err(Error::$err(value.to_owned()))
181 }
182 }
183 }
184
185 impl TryFrom<BigUint> for $int {
186 type Error = Error;
187
188 fn try_from(value: BigUint) -> Result<Self, Self::Error> {
190 <$int>::try_from(&value)
191 }
192 }
193
194 impl TryFrom<&BigInt> for $int {
195 type Error = Error;
196
197 fn try_from(value: &BigInt) -> Result<Self, Self::Error> {
199 use num_traits::{Signed, Zero};
200 if value < &BigInt::from_slice(num_bigint::Sign::Minus, Self::MAX_ABS_ARR) || value > &BigInt::from_slice(num_bigint::Sign::Plus, Self::MAX_ABS_ARR) {
201 let abs = value.abs().to_biguint().unwrap();
202 Err(Error::$err(abs))
203 } else if value == &BigInt::zero() {
204 Ok(Self::default())
205 } else if value < &BigInt::zero() {
206 Ok(Self {
207 sign: Sign::Neg,
208 data: value.abs().to_biguint().unwrap(),
209 })
210 } else {
211 Ok(Self {
212 sign: Sign::Pos,
213 data: value.to_biguint().unwrap(),
214 })
215 }
216 }
217 }
218
219 impl TryFrom<BigInt> for $int {
220 type Error = Error;
221
222 fn try_from(value: BigInt) -> Result<Self, Self::Error> {
224 <$int>::try_from(&value)
225 }
226 }
227 )+
228 };
229}
230
231#[cfg(feature = "bigint")]
232impl_try_from_big! {
233 MyriadScaleBigInt, MyriadScaleOutOfRange,
234 MidScaleBigInt, MidScaleOutOfRange,
235 LongScaleBigInt, LongScaleOutOfRange,
236}