num_digitize/
lib.rs

1#![doc(html_root_url = "https://lunemec.github.io/rust-num-digitize/")]
2extern crate num;
3
4use std::iter::IntoIterator;
5use std::ops::DivAssign;
6use num::{Num, NumCast, cast};
7
8
9pub trait ToDigits
10where Self: Copy + Clone + Num + NumCast + DivAssign {
11    /// Converts integer to `Vec<i8>` of its digits (base 10).
12    ///
13    /// # Example
14    ///
15    /// Basic usage:
16    ///
17    /// ```
18    /// use num_digitize::ToDigits;
19    ///
20    /// let number: u8 = 12;
21    /// let vector: Vec<i8> = vec![1, 2];
22    /// assert_eq!(number.to_digits(), vector);
23    /// ```
24    ///
25    /// Negative numbers return all the digits negative `Vec<u8>`:
26    ///
27    /// ```
28    /// use num_digitize::ToDigits;
29    /// let number = -12;
30    /// assert_eq!(number.to_digits(), vec![-1, -2]);
31    /// ```
32    ///
33    /// Reason for this is mathematically you can easily add these back to the original number like so:
34    ///
35    /// ```text
36    /// -123 -> [-1, -2, -3]
37    /// (-1 * 10^2) + (-2 * 10^1) + (-3 * 10^0) = -123
38    /// ```
39    ///
40    /// Or with `FromDigits` trait.
41    fn to_digits(&self) -> Vec<i8> {
42        let mut number = self.clone();
43        let mut digits: Vec<i8> = Vec::new();
44
45        let zero: Self = cast(0).unwrap();
46        let ten: Self = cast(10).unwrap();
47
48        while number != zero {
49            let remainder: i8 = cast(number % ten).unwrap();
50            digits.insert(0, remainder);
51            number /= ten;
52        }
53
54        digits
55    }
56}
57
58pub trait FromIterRadix  // Thank you *insaneinside*!
59where Self: Copy + Sized + Num + NumCast {
60    /// Converts a iterable of numbers back to original number of given base.
61    ///
62    /// # Example
63    ///
64    /// Basic usage:
65    ///
66    /// ```
67    /// use num_digitize::FromIterRadix;
68    ///
69    /// let original_number = 12345678;
70    /// let output = i8::from_iter_radix([1, 2, 3, 4, 5, 6, 7, 8].iter().cloned(), 10);
71    /// assert_eq!(original_number, output);
72    /// ```
73    ///
74    /// Please note, bases other than 10 were not tested and may not give any sense!
75    fn from_iter_radix<I: IntoIterator<Item=Self>>(iter: I, base: i64) -> i64 {
76        iter.into_iter().fold(
77            0i64,
78            |mut sum: i64, number| {sum *= base; sum += cast::<Self,i64>(number).unwrap(); sum}
79        )
80    }
81}
82
83pub trait FromDigits<N>
84where N: FromIterRadix, Self: Sized + IntoIterator<Item=N> {
85    /// Converts iterable of digits back to the original number.
86    /// This does not currently work for slices.
87    ///
88    /// # Example
89    ///
90    /// Basic usage:
91    ///
92    /// ```
93    /// use num_digitize::FromDigits;
94    ///
95    /// let vector = vec![1, 2, 3, 4, 5];
96    /// let number = 12345;
97    /// assert_eq!(vector.from_digits(), number);
98    /// ```
99    ///
100    /// Negative numbers:
101    ///
102    /// ```
103    /// use num_digitize::FromDigits;
104    ///
105    /// let vector = vec![-1, -2, -3, -4, -5];
106    /// let number = -12345;
107    /// assert_eq!(vector.from_digits(), number);
108    /// ```
109    ///
110    /// It works like this:
111    /// ```text
112    /// [-1, -2, -3]
113    /// (-1 * 10^2) + (-2 * 10^1) + (-3 * 10^0) = -123
114    /// ```
115    ///
116    /// Please note, all of the digits have to be negative in order to get the correct number back.
117    ///
118    /// Also note, if you use this on vector of larger numbers (> 9 or < -9), the results will be
119    /// wrong.
120    ///
121    /// See `ToDigits` trait for details.
122    fn from_digits(self) -> i64 {
123        N::from_iter_radix(self, 10i64)
124    }
125}
126
127impl ToDigits for i8 {}
128impl ToDigits for i16 {}
129impl ToDigits for i32 {}
130impl ToDigits for i64 {}
131impl ToDigits for isize {}
132impl ToDigits for u8 {}
133impl ToDigits for u16 {}
134impl ToDigits for u32 {}
135impl ToDigits for u64 {}
136impl ToDigits for usize {}
137
138impl FromIterRadix for i8 {}
139impl FromIterRadix for i16 {}
140impl FromIterRadix for i32 {}
141impl FromIterRadix for i64 {}
142impl FromIterRadix for isize {}
143impl FromIterRadix for u8 {}
144impl FromIterRadix for u16 {}
145impl FromIterRadix for u32 {}
146impl FromIterRadix for u64 {}
147impl FromIterRadix for usize {}
148
149impl<I, N> FromDigits<N> for I where N: FromIterRadix, I: IntoIterator<Item=N> {}
150
151#[cfg(test)]
152mod to_digits {
153    use super::ToDigits;
154
155    #[test]
156    fn test_zero() {
157        let i = 0;
158        let vector: Vec<i8> = vec![];
159        assert_eq!(i.to_digits(), vector);
160    }
161
162    #[test]
163    fn test_i8() {
164        let i: i8 = 123;
165        let vector: Vec<i8> = vec![1, 2, 3];
166        assert_eq!(i.to_digits(), vector);
167    }
168
169    #[test]
170    fn test_i8_negative() {
171        let i: i8 = -56;
172        let vector: Vec<i8> = vec![-5, -6];
173        assert_eq!(i.to_digits(), vector);
174    }
175
176    #[test]
177    fn test_i16() {
178        let i: i16 = 12366;
179        let vector: Vec<i8> = vec![1, 2, 3, 6, 6];
180        assert_eq!(i.to_digits(), vector);
181    }
182
183    #[test]
184    fn test_i32() {
185        let i: i32 = 4555;
186        let vector: Vec<i8> = vec![4, 5, 5, 5];
187        assert_eq!(i.to_digits(), vector);
188    }
189
190    #[test]
191    fn test_i64() {
192        let i: i64 = 45559;
193        let vector: Vec<i8> = vec![4, 5, 5, 5, 9];
194        assert_eq!(i.to_digits(), vector);
195    }
196
197    #[test]
198    fn test_isize() {
199        let i: isize = 4555934;
200        let vector: Vec<i8> = vec![4, 5, 5, 5, 9, 3, 4];
201        assert_eq!(i.to_digits(), vector);
202    }
203
204    #[test]
205    fn test_u8() {
206        let i: u8 = 255;
207        let vector: Vec<i8> = vec![2, 5, 5];
208        assert_eq!(i.to_digits(), vector);
209    }
210
211    #[test]
212    fn test_u16() {
213        let i: u16 = 25945;
214        let vector: Vec<i8> = vec![2, 5, 9, 4, 5];
215        assert_eq!(i.to_digits(), vector);
216    }
217
218    #[test]
219    fn test_u32() {
220        let i: u32 = 2591222345;
221        let vector: Vec<i8> = vec![2, 5, 9, 1, 2, 2, 2, 3, 4, 5];
222        assert_eq!(i.to_digits(), vector);
223    }
224
225    #[test]
226    fn test_u64() {
227        let i: u64 = 12341234765432;
228        let vector: Vec<i8> = vec![1, 2, 3, 4, 1, 2, 3, 4, 7, 6, 5, 4, 3, 2];
229        assert_eq!(i.to_digits(), vector);
230    }
231
232    #[test]
233    fn test_usize() {
234        let i: usize = 1234567890;
235        let vector: Vec<i8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
236        assert_eq!(i.to_digits(), vector);
237    }
238
239}
240
241#[cfg(test)]
242mod from_iter_radix {
243    use super::FromIterRadix;
244
245    #[test]
246    fn test_vector_i8() {
247        let i = 12345678;
248        let result = i8::from_iter_radix(vec![1, 2, 3, 4, 5, 6, 7, 8], 10);
249        assert_eq!(i, result);
250    }
251
252    #[test]
253    fn test_slice_i8() {
254        let i = 12345678;
255        let result = i8::from_iter_radix([1, 2, 3, 4, 5, 6, 7, 8].iter().cloned(), 10);
256        assert_eq!(i, result);
257    }
258}
259
260#[cfg(test)]
261mod from_digits {
262    use super::FromDigits;
263
264    #[test]
265    fn test_zero() {
266        let i = 0;
267        let vector: Vec<i8> = vec![];
268        assert_eq!(vector.from_digits(), i);
269    }
270
271    #[test]
272    fn test_multiple_zeros() {
273        let i = 0;
274        let vector: Vec<i8> = vec![0, 0, 0, 0, 0, 0, 0];
275        assert_eq!(vector.from_digits(), i);
276    }
277
278    #[test]
279    fn test_i8() {
280        let i = 123;
281        let vector: Vec<i8> = vec![1, 2, 3];
282        assert_eq!(vector.from_digits(), i);
283    }
284
285    #[test]
286    fn test_i8_negative() {
287        let i = -56;
288        let vector: Vec<i8> = vec![-5, -6];
289        assert_eq!(vector.from_digits(), i);
290    }
291
292    #[test]
293    fn test_i16() {
294        let i = 12366;
295        let vector: Vec<i16> = vec![1, 2, 3, 6, 6];
296        assert_eq!(vector.from_digits(), i);
297    }
298
299    #[test]
300    fn test_i32() {
301        let i = 4555;
302        let vector: Vec<i32> = vec![4, 5, 5, 5];
303        assert_eq!(vector.from_digits(), i);
304    }
305
306    #[test]
307    fn test_i64() {
308        let i = 45559;
309        let vector: Vec<i64> = vec![4, 5, 5, 5, 9];
310        assert_eq!(vector.from_digits(), i);
311    }
312
313    #[test]
314    fn test_u8() {
315        let i = 255;
316        let vector: Vec<u8> = vec![2, 5, 5];
317        assert_eq!(vector.from_digits(), i);
318    }
319
320    #[test]
321    fn test_isize() {
322        let i = 455597;
323        let vector: Vec<isize> = vec![4, 5, 5, 5, 9, 7];
324        assert_eq!(vector.from_digits(), i);
325    }
326
327    #[test]
328    fn test_u16() {
329        let i = 25945;
330        let vector: Vec<u16> = vec![2, 5, 9, 4, 5];
331        assert_eq!(vector.from_digits(), i);
332    }
333
334    #[test]
335    fn test_u32() {
336        let i = 2591222345;
337        let vector: Vec<u32> = vec![2, 5, 9, 1, 2, 2, 2, 3, 4, 5];
338        assert_eq!(vector.from_digits(), i);
339    }
340
341    #[test]
342    fn test_u64() {
343        let i = 12341234765432;
344        let vector: Vec<u64> = vec![1, 2, 3, 4, 1, 2, 3, 4, 7, 6, 5, 4, 3, 2];
345        assert_eq!(vector.from_digits(), i);
346    }
347
348    #[test]
349    fn test_usize() {
350        let i = 1234567890;
351        let vector: Vec<usize> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
352        assert_eq!(vector.from_digits(), i);
353    }
354
355    #[test]
356    fn test_negative() {
357        let i = -25945;
358        let vector = vec![-2, -5, -9, -4, -5];
359        assert_eq!(vector.from_digits(), i);
360    }
361}