1use std::{vec};
6use error::INIDError;
7use rand::Rng;
8
9pub mod error;
10
11const INID_LENGTH:u8 = 10;
12const DECIMAL_RADIX:u8 = 10;
13type INID = Vec<u8>;
14
15
16fn generate_checksum(nid:&INID) -> u8{
19 let mut n_sum: u16 = 0;
20 for p in (2..=10).rev(){
21 n_sum += (nid[10 - p] as u16) * (p as u16);
22 }
23 let r = n_sum % 11 ;
24 let checksum:u8 = if r < 2 {r as u8} else {11 - r as u8};
25 checksum
26}
27
28pub fn generate_id(prefix:Option<&String>) -> Result<String,INIDError>{
37
38 match prefix {
39 Some(prefix) =>{
40
41 let mut inid = convert_str_to_inid(&prefix)?;
42
43 for _ in 0..9-inid.len(){
44 let random_number = rand::thread_rng().gen_range(0..=9);
45 inid.push(random_number);
46 }
47
48 let checksum = generate_checksum(&inid);
49 inid.push(checksum);
50
51 return Ok(convert_inid_to_str(&inid))
52 },
53 None =>{
54 let mut inid :Vec<u8> = vec![];
55
56 for _ in 1..=9{
57 let random_number = rand::thread_rng().gen_range(0..=9);
58 inid.push(random_number);
59 }
60
61 let checksum = generate_checksum(&inid);
62 inid.push(checksum);
63
64 Ok(convert_inid_to_str(&inid))
65 }
66 }
67}
68
69pub fn check_inid(s_inid:&String) -> Result<bool,INIDError>{
78 if s_inid.chars().count() != INID_LENGTH as usize{
79 return Err(INIDError::InvalidLength)
80 }
81 if !s_inid.chars().all(|c| c.is_numeric()){
82 return Err(INIDError::NotNumerical)
83 }
84 let inid = convert_str_to_inid(s_inid)?;
85 Ok(generate_checksum(&inid) == inid[inid.len()-1])
86}
87
88fn convert_inid_to_str(inid:&INID) -> String{
91 let mut s = String::from("");
92 for item in inid{
93 s.push_str(&item.to_string());
94 }
95 s
96}
97fn convert_str_to_inid(input:&String) -> Result<INID,INIDError>{
99
100 let mut nid: Vec<u8> = vec![];
101 for s in input.chars(){
102 if s == ' '{
103 continue;
104 }
105 match s.to_digit(DECIMAL_RADIX as u32){
106 Some(char_digit) => nid.push(char_digit as u8),
107 None => return Err(error::INIDError::NotNumerical),
108 }
109 }
110 Ok(nid)
111}
112
113#[cfg(test)]
114mod tests {
115
116 use super::*;
117
118 #[test]
119 fn generate_id_test() {
120 let result = generate_id(None);
122 match result{
123 Ok(v) => {
124
125 let inid = match convert_str_to_inid(&v){
126 Ok(v) =>v,
127 Err(e) => panic!("{}",e)
128 };
129
130 let res_len = inid.len();
131
132 assert_eq!(res_len,10);
134
135 assert_eq!(inid[res_len -1],generate_checksum(&inid))
137 },
138 Err(e) => {panic!("{}",e)},
139 }
140 let result = generate_id(Some(&"123".to_string()));
142 match result{
143 Ok(v) => {
144
145 let inid = match convert_str_to_inid(&v){
146 Ok(v) =>v,
147 Err(e) => panic!("{}",e)
148 };
149
150 let res_len = inid.len();
151
152 assert_eq!(res_len,10);
154
155 assert_eq!(inid[res_len -1],generate_checksum(&inid))
157 },
158 Err(e) => {panic!("{}",e)},
159 }
160 }
161
162 #[test]
163 fn check_id_and_generate_checksum_test(){
164 let ids:Vec<INID> = vec![vec![2,3,5,7,2,1,4,8,1,3],vec![8,7,4,7,6,2,3,6,6,7],vec![4,5,7,5,9,0,0,7,6,1]];
165 for item in ids{
166 let checksum = generate_checksum(&item);
167 assert_eq!(checksum,item[item.len()-1]);
168 }
169 }
170
171}