json_template/placeholder/
mod.rs

1//! Placeholder module.
2
3use crate::Path;
4
5/// This struct represents a placeholder in a JSON object.
6#[derive(Debug, Clone)]
7pub struct Placeholder {
8    /// The placeholder value.
9    pub value: String,
10    /// The placeholder type.
11    pub type_: Option<String>,
12}
13
14impl Placeholder {
15    /// Get all the placeholders in a string.
16    /// If value == "{time} {time:3}", then placeholders == ["{time}", "{time:3}"].
17    /// If value == "{time:{time:5}}  {time}", then placeholders == ["{time:{time:5}}", "{time}"].
18    pub fn placeholders(value: &str) -> Vec<Self> {
19        let mut levels = 0;
20        let mut current_placeholder = String::new();
21        let mut placeholders = Vec::new();
22        for character in value.chars() {
23            match character {
24                '{' => {
25                    if levels == 0 {
26                        current_placeholder.clear();
27                    }
28                    levels += 1;
29                    current_placeholder.push(character);
30                }
31                '}' => {
32                    levels -= 1;
33                    current_placeholder.push(character);
34                    if levels == 0 {
35                        placeholders.push(Self::from_str(&current_placeholder).expect("Failed to create placeholder."));
36                    }
37                }
38                _ => {
39                    if levels > 0 {
40                        current_placeholder.push(character);
41                    }
42                }
43            }
44        }
45        placeholders
46    }
47
48    /// Create a new placeholder from a string.
49    pub fn from_str(value: &str) -> Option<Self> {
50        if value.starts_with('{') && value.ends_with('}') {
51            let value = value.to_string();
52            let chars = value.chars();
53            let first = chars.clone().nth(0);
54            let second = chars.clone().nth(1);
55            let type_ = first.zip(second).map(|(first, second)| {
56                if first == '{' && second.is_alphanumeric() {
57                    value.find(':').map(|index| value[1 .. index].to_string())
58                } else {
59                    None
60                }
61            }).flatten();
62            Some(Self { value, type_ })
63        } else {
64            None
65        }
66    }
67
68    /// Get the path of the placeholder.
69    pub fn path(&self) -> Path {
70        if let Some(type_) = &self.type_ {
71            Path::new(&self.value[type_.len() + 2 .. self.value.len() - 1])
72        } else {
73            Path::new(&self.value[1 .. self.value.len() - 1])
74        }
75    }
76}
77