1use serde::Deserialize;
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
5#[serde(rename_all = "snake_case")]
6pub enum EncodingMode {
7 BaseConversion,
8 Chunked,
9}
10
11impl Default for EncodingMode {
12 fn default() -> Self {
13 EncodingMode::BaseConversion
14 }
15}
16
17#[derive(Debug, Deserialize, Clone)]
18pub struct AlphabetConfig {
19 pub chars: String,
20 #[serde(default)]
21 pub mode: EncodingMode,
22 #[serde(default)]
23 pub padding: Option<String>,
24}
25
26#[derive(Debug, Deserialize)]
27pub struct AlphabetsConfig {
28 pub alphabets: HashMap<String, AlphabetConfig>,
29}
30
31impl AlphabetsConfig {
32 pub fn from_toml(content: &str) -> Result<Self, toml::de::Error> {
33 toml::from_str(content)
34 }
35
36 pub fn load_default() -> Result<Self, Box<dyn std::error::Error>> {
37 let content = include_str!("../alphabets.toml");
38 Ok(Self::from_toml(content)?)
39 }
40
41 pub fn get_alphabet(&self, name: &str) -> Option<&AlphabetConfig> {
42 self.alphabets.get(name)
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn test_load_default_config() {
52 let config = AlphabetsConfig::load_default().unwrap();
53 assert!(config.alphabets.contains_key("cards"));
54 }
55
56 #[test]
57 fn test_cards_alphabet_length() {
58 let config = AlphabetsConfig::load_default().unwrap();
59 let cards = config.get_alphabet("cards").unwrap();
60 assert_eq!(cards.chars.chars().count(), 52);
61 }
62
63 #[test]
64 fn test_base64_chunked_mode() {
65 let config = AlphabetsConfig::load_default().unwrap();
66 let base64 = config.get_alphabet("base64").unwrap();
67 assert_eq!(base64.mode, EncodingMode::Chunked);
68 assert_eq!(base64.padding, Some("=".to_string()));
69 }
70
71 #[test]
72 fn test_base64_math_mode() {
73 let config = AlphabetsConfig::load_default().unwrap();
74 let base64_math = config.get_alphabet("base64_math").unwrap();
75 assert_eq!(base64_math.mode, EncodingMode::BaseConversion);
76 }
77}
78