coc_rs/util/
logic_long_to_code_converter_util.rs

1use super::LogicLong;
2
3#[derive(Debug)]
4pub struct LogicLongToCodeConverterUtil {
5    hash_tag: String,
6    conversion_chars: String,
7}
8
9impl LogicLongToCodeConverterUtil {
10    pub fn new(hash_tag: &str, conversion_chars: &str) -> Self {
11        Self { hash_tag: hash_tag.to_string(), conversion_chars: conversion_chars.to_string() }
12    }
13
14    pub fn to_code(&self, logic_long: LogicLong) -> String {
15        let high_value = i64::from(logic_long.get_higher_int());
16
17        if high_value < 256 {
18            return self.hash_tag.clone()
19                + &self.convert((i64::from(logic_long.get_lower_int()) << 8) | high_value);
20        }
21
22        #[cfg(feature = "tracing")]
23        tracing::trace!("Cannot convert the code to string. Higher int value too large");
24        String::new()
25    }
26
27    pub fn to_id(&self, code: &str) -> LogicLong {
28        if code.len() < 14 {
29            let id_code = code.replace(self.hash_tag.as_str(), "");
30            let id = self.convert_code(&id_code);
31
32            if id != -1 {
33                return LogicLong::new((id % 256) as i32, ((id >> 8) & 0x7FFF_FFFF) as i32);
34            }
35        } else {
36            #[cfg(feature = "tracing")]
37            tracing::trace!("Cannot convert the string to code. String is too long.");
38        }
39
40        LogicLong::new(-1, -1)
41    }
42
43    pub fn convert_code(&self, code: &str) -> i64 {
44        let mut id: i64 = 0;
45        let conversion_chars_count = self.conversion_chars.len();
46        let code_chars_count = code.len();
47
48        for i in 0..code_chars_count {
49            let char_index = self.conversion_chars.find(code.chars().nth(i).unwrap());
50
51            if char_index.is_none() {
52                #[cfg(feature = "tracing")]
53                tracing::trace!(
54                    "Cannot convert the string to code. String contains invalid character(s)."
55                );
56                id = -1;
57                break;
58            }
59
60            id = id * conversion_chars_count as i64 + char_index.unwrap() as i64;
61        }
62
63        id
64    }
65
66    fn convert(&self, mut value: i64) -> String {
67        if value > -1 {
68            let conversion_chars_count = self.conversion_chars.len();
69            let mut code = [' '; 12];
70
71            for i in (0..12).rev() {
72                let Ok(index) = usize::try_from(value % conversion_chars_count as i64) else {
73                    #[cfg(feature = "tracing")]
74                    tracing::trace!(
75                        "LogicLongToCodeConverter: value to convert ({}) cannot be negative!",
76                        value
77                    );
78
79                    return String::new();
80                };
81                if let Some(char) = self.conversion_chars.get(index..=index) {
82                    code[i] = char.chars().next().unwrap();
83                }
84                value /= conversion_chars_count as i64;
85
86                if value == 0 || i == 0 {
87                    let start_idx = code.iter().take_while(|&&c| c == ' ').count();
88                    let mut result = String::with_capacity(12 - start_idx);
89                    for ch in &code[start_idx..] {
90                        result.push(*ch);
91                    }
92                    return result;
93                }
94            }
95        }
96
97        #[cfg(feature = "tracing")]
98        tracing::trace!("LogicLongToCodeConverter: value to convert cannot be negative");
99
100        String::new()
101    }
102}