1use std::collections::VecDeque;
2
3pub fn decrypt(s: &str) -> Option<String> {
14 let mut data = VecDeque::<char>::new();
15
16 for c in s.chars().collect::<Vec<_>>().chunks(2) {
17 if c.len() < 2 {
18 return None;
19 }
20 data.push_back(c[0]);
21 data.push_front(c[1]);
22 }
23
24 data.rotate_left(data.len() / 2);
25
26 data.iter()
27 .enumerate()
28 .filter_map(|(j, val)| {
29 val.to_string()
30 .trim()
31 .parse::<i32>()
32 .map(|val_parsed| (j, val_parsed))
33 .ok()
34 })
35 .collect::<Vec<_>>()
36 .chunks_exact(2)
37 .for_each(|items| {
38 if let [x, y] = items {
39 let xor = x.1 ^ y.1;
40 if xor < 10 {
41 data[x.0] = xor.to_string().parse().unwrap();
42 }
43 }
44 });
45
46 let base64_enc = data.drain(..).collect::<String>();
47
48 match base64::decode(base64_enc) {
49 Ok(s) => String::from_utf8(s).ok(),
50 _ => None,
51 }
52}
53pub fn encrypt(s: &str) -> Option<String> {
64 let base64_enc = base64::encode(s.as_bytes());
65 let mut data = base64_enc.as_bytes().to_vec();
66 let mut first: Option<(usize, u8)> = None;
67 for (i, c) in base64_enc.as_bytes().iter().enumerate() {
68 if (0x30..0x3a).any(|x| x == *c) {
69 if let Some(s) = first {
70 let f = s.1 ^ (c - 0x30);
71 if f < 10 {
72 data[s.0] = f + 0x30;
73 }
74 first = None;
75 } else {
76 first = Some((i, c - 0x30));
77 }
78 }
79 }
80
81 let mut ss = vec![];
82 for i in 0..data.len() / 2 {
83 ss.push(data[i]);
84 ss.push(data[data.len() - 1 - i]);
85 }
86 if data.len() % 2 > 0 {
87 ss.push(data[data.len() / 2 + 1]);
88 }
89 String::from_utf8(ss).ok()
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_encrypt_decrypt() {
98 let original = "hello world";
99 let encoded = encrypt(original);
100 assert!(encoded.is_some());
101 let decoded = decrypt(&encoded.unwrap());
102 assert!(decoded.is_some());
103 assert_eq!(decoded.unwrap(), original);
104 }
105}