1extern crate num;
2extern crate num_digitize;
3
4use num::*;
5use num_digitize::ToDigits;
6
7
8fn take_digits<F>(card_number_digits: &Vec<i8>, mut take_function: F) -> Vec<i8>
13 where F: FnMut(&usize) -> bool
14{
15 let mut result: Vec<i8> = Vec::new();
16 for item in card_number_digits.iter().enumerate() {
17 if take_function(&item.0) {
18 result.insert(0, *item.1);
19 }
20 }
21 result
22}
23
24fn sum(vector: &Vec<i8>) -> u64 {
27 let mut result: u64 = 0;
28 for item in vector {
29 result += *item as u64;
30 }
31 result
32}
33
34
35pub fn validate(number: u64) -> bool {
50 let vec = {
51 let mut vec = number.to_digits();
52 vec.reverse();
53 vec
54 };
55
56 let odd_sum: u64 = sum(&take_digits(&vec, Integer::is_even));
58 let even_sum: u64 = {
59 let mut even_sum: u64 = 0;
60 let even_digits = take_digits(&vec, Integer::is_odd);
62 for even_digit in even_digits.iter().map(|x| x * 2) {
64 even_sum += sum(&even_digit.to_digits());
66 }
67 even_sum
68 };
69
70 let luhn = odd_sum + even_sum;
71 return luhn % 10 == 0;
72}
73
74
75#[test]
76fn test_sum() {
77 assert!(sum(&vec![1, 2, 3, 4]) == 10);
78 assert!(sum(&vec![]) == 0);
79}
80
81#[test]
82fn test_take_digits() {
83 let test_digits = vec![0, 1, 2, 3, 4, 5, 6];
84 assert!(take_digits(&test_digits, Integer::is_even) == vec![6, 4, 2, 0]);
85 assert!(take_digits(&test_digits, Integer::is_odd) == vec![5, 3, 1]);
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_ok_numbers() {
94 assert!(validate(49927398716));
95 assert!(validate(1234567812345670));
96 assert!(validate(79927398713));
97 }
98
99 #[test]
100 fn test_invalid_numbers() {
101 assert!(validate(4242424242424241) == false);
102 assert!(validate(49927398717) == false);
103 assert!(validate(1234567812345678) == false);
104 }
105}