cryptography_breaker/
validator.rs1use std::{collections::HashSet, fmt::Display};
6
7use crate::normalizer;
8
9pub enum ValidateAlphabetError {
11 CharacterExistInDifferentCase(char),
13 DuplicateCharacter(char),
15 InvalidCharacter(char),
17 EmptyAlphabet,
19}
20impl Display for ValidateAlphabetError {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 match self {
23 ValidateAlphabetError::CharacterExistInDifferentCase(c) => write!(
24 f,
25 "There is already the same character but in different case: {}",
26 c
27 ),
28 ValidateAlphabetError::DuplicateCharacter(c) => {
29 write!(f, "There is already the same character: {}", c)
30 }
31 ValidateAlphabetError::InvalidCharacter(c) => {
32 write!(f, "Invalid character: {}", c)
33 }
34 ValidateAlphabetError::EmptyAlphabet => {
35 write!(f, "Alphabet cannot be empty")
36 }
37 }
38 }
39}
40pub enum ValidateInputTextError {
42 CharacterNotInAlphabet(char),
44 LowerCaseCharacter(char),
46}
47impl Display for ValidateInputTextError {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 ValidateInputTextError::CharacterNotInAlphabet(c) => {
51 write!(f, "There is no such a character inside the alphabet: {}", c)
52 }
53 ValidateInputTextError::LowerCaseCharacter(c) => {
54 write!(
55 f,
56 "Lower case characters are not allowed for your configuration. Consider using CaseSensitive option: {}",
57 c
58 )
59 }
60 }
61 }
62}
63pub fn validate_alphabet(
65 alphabet: &[char],
66 case_strategy: normalizer::CaseStrategy,
67) -> Result<(), ValidateAlphabetError> {
68 if alphabet.is_empty() {
69 return Err(ValidateAlphabetError::EmptyAlphabet)
70 }
71 match case_strategy {
72 normalizer::CaseStrategy::CaseSensitive => {
73 let mut checked = HashSet::new();
74 for c in alphabet {
75 if !checked.insert(c) {
76 return Err(ValidateAlphabetError::DuplicateCharacter(*c));
77 }
78 }
79 Ok(())
80 }
81 normalizer::CaseStrategy::CaseUnsensitive => {
82 let mut checked = HashSet::new();
83 for c in alphabet {
84 if !checked.insert(*c) {
85 return Err(ValidateAlphabetError::DuplicateCharacter(*c));
86 } else {
87 let c = c
88 .to_uppercase()
89 .next()
90 .ok_or(ValidateAlphabetError::InvalidCharacter(*c))?;
91 if !checked.insert(c) {
92 return Err(ValidateAlphabetError::CharacterExistInDifferentCase(c));
93 }
94 }
95 }
96 Ok(())
97 }
98
99 normalizer::CaseStrategy::Preserve => {
100 let mut checked = HashSet::new();
101 for c in alphabet {
102 if !checked.insert(*c) {
103 return Err(ValidateAlphabetError::DuplicateCharacter(*c));
104 } else {
105 let upper_c = c
106 .to_uppercase()
107 .next()
108 .ok_or(ValidateAlphabetError::InvalidCharacter(*c))?;
109 if !checked.insert(upper_c) {
110 return Err(ValidateAlphabetError::CharacterExistInDifferentCase(
111 upper_c,
112 ));
113 }
114 }
115 }
116 Ok(())
117 }
118 }
119}
120
121pub fn validate_input_text(
123 input_text: &str,
124 case_strategy: normalizer::CaseStrategy,
125 alphabet: &[char],
126 preserve_whitespaces: bool,
127 preserve_other_characters: bool,
128) -> Result<(), ValidateInputTextError> {
129 if preserve_other_characters {
131 return Ok(());
132 }
133
134 match case_strategy {
135 normalizer::CaseStrategy::CaseSensitive => {
136 for c in input_text.chars() {
137 if preserve_whitespaces && c.is_whitespace() {
138 return Ok(());
139 }
140 if !alphabet.contains(&c) {
141 return Err(ValidateInputTextError::CharacterNotInAlphabet(c));
142 }
143 }
144 Ok(())
145 }
146 normalizer::CaseStrategy::CaseUnsensitive => {
147 for c in input_text.chars() {
148 if preserve_whitespaces && c.is_whitespace() {
149 return Ok(());
150 }
151 if c.is_lowercase() {
152 return Err(ValidateInputTextError::LowerCaseCharacter(c));
153 }
154 if !alphabet.contains(&c) {
155 return Err(ValidateInputTextError::CharacterNotInAlphabet(c));
156 }
157 }
158 Ok(())
159 }
160 normalizer::CaseStrategy::Preserve => {
161 for c in input_text.chars() {
162 if preserve_whitespaces && c.is_whitespace() {
163 return Ok(());
164 }
165 if c.is_lowercase() {
166 return Err(ValidateInputTextError::LowerCaseCharacter(c));
167 }
168 if !alphabet.contains(&c) {
169 return Err(ValidateInputTextError::CharacterNotInAlphabet(c));
170 }
171 }
172 Ok(())
173 }
174 }
175}
176
177pub fn validate_key() {}