localoco/
util.rs

1//! This module contains some utility functions that you may use in your application.
2
3use std::{path::{Path, PathBuf}, io::Read};
4
5use crate::strings::Strings;
6
7/// Loads a strings file from a given path.
8/// It will loads the file called `{name}.loc` under the given path.
9pub fn load_strings<P: AsRef<Path>>(path: P, name: &str) -> Result<Strings, std::io::Error> {
10    let mut pathbuf = PathBuf::from(path.as_ref());
11    pathbuf.push(&format!("{}.loc", name));
12    let mut f = std::fs::OpenOptions::new().read(true).open(pathbuf)?;
13    let mut buffer = Vec::new();
14    f.read_to_end(&mut buffer)?;
15    match Strings::load(&buffer) {
16        Ok(obj) => Ok(obj),
17        Err(err) => Err(std::io::Error::new(std::io::ErrorKind::Other, err))
18    }
19}
20
21/// Insert contents into the placeholders in the string.
22/// A brief example of a string with placeholders:
23/// 
24/// ```
25/// "Placeholder is a {0} with something that needs to be inserted {1}. {{{{}}}} can be used when
26/// you want to express {{ or }}"
27/// ```
28/// 
29pub fn insert(fmt: &str, args: &[&str]) -> String {
30    let mut result = String::new();
31    let mut buffer = String::new();
32    let mut state = 0;
33
34    for i in fmt.chars() {
35        match state {
36            0 => {
37                match i {
38                    '{' => {
39                        state = 1;
40                    }
41                    '}' => {
42                        state = 3;
43                    }
44                    _ => {
45                        result.push(i);
46                    }
47                }
48            }
49            1 => {
50                match i {
51                    '{' => {
52                        result.push('{');
53                        state = 0;
54                    }
55                    '0'..='9' => {
56                        state = 2;
57                        buffer.push(i);
58                    }
59                    _ => {
60                        state = 0;
61                    }
62                }
63            }
64            2 => {
65                match i {
66                    '0'..='9' => {
67                        buffer.push(i);
68                    }
69                    '}' => {
70                        if let Ok(idx) = str::parse::<usize>(&buffer) {
71                            if idx < args.len() {
72                                result.push_str(args[idx]);
73                            } else {
74                                result.push_str("<failed insertion due to array out-of-range>")
75                            }
76                        } else {
77                            result.push_str("<failed insertion due to invalid number format>")
78                        }
79                        buffer = String::new();
80                        state = 0;
81                    }
82                    _ => {
83                        return "<invalid format>".into();
84                    }
85                }
86            }
87            3 => {
88                match i {
89                    '}' => {
90                        buffer.push('}');
91                        state = 0;
92                    }
93                    any => {
94                        buffer.push('}');
95                        buffer.push(any);
96                        state = 0;
97                    }
98                }
99            }
100            _ => {}
101        }
102    }
103
104    result
105}
106
107#[allow(unused)]
108mod test {
109    use super::insert;
110
111
112    #[test]
113    fn test_insert() {
114        let result = insert("The {2} fox jumps {0} the lazy {1}{20}", 
115        &[
116            "over", "dog", "brown", "", "", "",
117            "over", "dog", "brown", "", "", "",
118            "over", "dog", "brown", "", "", "",
119            "over", "dog", "?", "", "", "",
120            "?", "dog", "brown", "", "", "",
121        ]
122    );
123        assert_eq!(result, "The brown fox jumps over the lazy dog?");
124    }
125
126}