cifra/
lib.rs

1#![feature(trace_macros)]
2#![feature(iter_advance_by)]
3#[macro_use]
4extern crate diesel;
5extern crate dotenv;
6
7pub mod attack;
8pub mod cipher;
9// pub mod errors;
10pub mod encoding;
11mod schema;
12
13#[macro_use]
14extern crate diesel_migrations;
15
16#[macro_use]
17extern crate error_chain;
18
19use crate::cipher::affine::WrongAffineKey;
20
21// Create the Error, ErrorKind, ResultExt, and Result types
22error_chain! {
23    types {
24        Error, ErrorKind, ResultExt, Result;
25    }
26    errors {
27            ConversionError(var: &'static str, var_type: &'static str, tried_type: &'static str) {
28                description("Conversion failed.")
29                display("{} type variable '{}' could not converted to {}", var_type, var, tried_type)
30            }
31            DatabaseError(message: String) {
32                description("Database error")
33                display("{}", message)
34            }
35            StringIndexError(searched_string: String, message: &'static str){
36                description("Error looking for a string.")
37                display("Error looking for {} text. Additional information: {}", searched_string, message)
38            }
39            IOError(file: String){
40                description("Error reading/writing file.")
41                display("Error reading/writing {} file.", file)
42            }
43            FolderError(folder: String){
44                description("Error creating folder.")
45                display("Error creating folder: {}", folder)
46            }
47            KeyError(key: String, message: String){
48                description("Error with given key.")
49                display("Problem with key {}:\n{}", key, message)
50            }
51            NotExistingLanguage(language_tried: String) {
52                description("You have tried to operate with a language that does not exist yet at database.")
53                display("Does not exist any dictionary for {} language", language_tried)
54            }
55            WrongAffineKeyError(wrong_key: WrongAffineKey){
56                description("You selected a wrong Affine key.")
57                display("{}", wrong_key)
58            }
59            WrongKeyLength(wrong_key: String, charset: String){
60                description("Wrong key used: Length is not the same than key one")
61                display("Key length is {} and charset length is {}", wrong_key.len(), charset.len())
62            }
63            WrongKeyRepeatedCharacters(wrong_key: String){
64                description("Wrong key used: Key uses repeated characters")
65                display("{}", wrong_key)
66            }
67            CharacterMappingError(wrong_char: String){
68                description("Error trying to substitute char.")
69                display("Char tried to substitute {}", wrong_char)
70            }
71            EmptyMapping {
72                description("Mapping has no more cipherletters.")
73                display("Empty mapping.")
74            }
75            NoMappingAvailable(word: String, dictionary: String){
76                description("No candidate mapping was found for word.")
77                display("Word was {} and tried dictionary was {}", word, dictionary)
78            }
79    }
80}
81
82/// Trait to use one-letter strings as chars.
83pub trait FromStr<T> {
84    /// Create a char from a one letter string.
85    fn fromStr(s: T) -> Self;
86}
87
88impl FromStr<&str> for char {
89    fn fromStr(s: &str) -> Self {
90        s.chars().next().expect(format!("Could not create char from given string: {}", s).as_str())
91    }
92}
93
94/// Trait to use to find substrings searching from a given index.
95pub trait FindFromIndex<T, U> {
96
97    /// Find text_to_find in text using index as start search position.
98    ///
99    /// # Parameters:
100    /// * text: Text to search into.
101    /// * text_to_find: text to look for.
102    /// * index: Start search position.
103    ///
104    /// # Returns:
105    /// * Index where text_to_find_was found, counted from text start.
106    fn findFromIndex(text: &T, text_to_find: U, index: usize) -> Option<usize>;
107}
108
109impl <U: AsRef<str>> FindFromIndex<String, U> for String {
110    fn findFromIndex(text: &String, text_to_find: U, index: usize) -> Option<usize> {
111        let mut text_iter = text.chars();
112        if let Ok(()) = text_iter.advance_by(index) {
113            let remaining_text: String = text_iter.collect();
114            match remaining_text.find(text_to_find.as_ref()) {
115                Some(current_index) => return Some(current_index + index),
116                None => None
117            }
118        } else {
119            None
120        }
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127
128    #[test]
129    fn test_find_from_index() {
130        let text = "This is a text where I want to find another text.".to_string();
131        let text_to_find = "text";
132        let expected_index: usize = 44;
133        if let Some(found_index) = String::findFromIndex(&text, text_to_find, 14) {
134            assert_eq!(found_index, expected_index);
135        } else {
136            assert!(false)
137        }
138    }
139
140}