1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3
4mod parsing;
5
6pub enum Token {
8 Separator(char),
10 Word(String),
12}
13
14impl Token {
15 pub fn tokenize(text: &str) -> Vec<Token> {
17 let mut word = String::new();
18 let mut res = vec![];
19 for ch in text.chars() {
20 match ch {
21 '\n' | ' ' | '.' | ',' | ':' | ';' |
22 '[' | ']' | '(' | ')' |
23 '“' | '"' | '”' | '’' |
24 '—' => {
25 if word.len() > 0 {
26 res.push(Token::Word(word));
27 word = String::new();
28 }
29 res.push(Token::Separator(ch));
30 }
31 _ => word.push(ch),
32 }
33 }
34
35
36 if word.len() > 0 {
37 res.push(Token::Word(word));
38 }
39
40 res
41 }
42}
43
44pub type Data = Vec<(String, String)>;
46
47pub fn new() -> Data {
51 vec![("".into(), "".into())]
52}
53
54pub fn save(file: &str, data: &Data) -> Result<(), std::io::Error> {
56 use std::fs::File;
57 use std::io::Write;
58
59 let mut file = File::create(file)?;
60 writeln!(file, "[")?;
61 let mut first = true;
62 for (from, to) in data {
63 if first {
64 first = false;
65 } else {
66 writeln!(file, ",")?;
67 }
68 write!(file, " [\n {:?},\n {:?}\n ]", from, to)?;
69 }
70 writeln!(file, "\n]")?;
71 Ok(())
72}
73
74pub fn load(file: &str) -> Result<Data, String> {
76 use std::fs::File;
77 use std::io::Read;
78
79 let mut file = File::open(file).map_err(|_|
80 "Could not open file".to_string())?;
81 let mut bytes = vec![];
82 file.read_to_end(&mut bytes).unwrap();
83 let source = String::from_utf8(bytes)
84 .map_err(|_| "Could not convert to UTF8 text".to_string())?;
85 parsing::parse_str(&source)
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn it_works() {
94 let a = parsing::parse_str(r#"[["a", "b"]]"#).unwrap();
95 assert_eq!(a, vec![("a".to_string(), "b".to_string())]);
96
97 let a = parsing::parse_str(r#"[["a", "b"], ["c", "d"]]"#).unwrap();
98 assert_eq!(a, vec![
99 ("a".to_string(), "b".to_string()),
100 ("c".to_string(), "d".to_string()),
101 ]);
102 }
103}