ftml/tree/
variables.rs

1/*
2 * tree/variables.rs
3 *
4 * ftml - Library to parse Wikidot text
5 * Copyright (C) 2019-2025 Wikijump Team
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21use super::clone::string_map_to_owned;
22use std::borrow::Cow;
23use std::collections::HashMap;
24
25pub type VariableMap<'t> = HashMap<Cow<'t, str>, Cow<'t, str>>;
26
27#[derive(Debug, Clone, Default, PartialEq, Eq)]
28pub struct VariableScopes {
29    scopes: Vec<VariableMap<'static>>,
30}
31
32impl VariableScopes {
33    #[inline]
34    pub fn new() -> Self {
35        VariableScopes::default()
36    }
37
38    pub fn get(&self, name: &str) -> Option<&str> {
39        for scope in self.scopes.iter().rev() {
40            if let Some(value) = scope.get(name) {
41                return Some(value);
42            }
43        }
44
45        None
46    }
47
48    pub fn push_scope(&mut self, scope: &VariableMap) {
49        // We clone here since managing multiple, scope-dependent
50        // lifetimes for each call is impractical, and we can't
51        // use Rc or RefCell because it is borrowed from Element.
52        self.scopes.push(string_map_to_owned(scope));
53    }
54
55    pub fn pop_scope(&mut self) {
56        self.scopes.pop().expect("Scope stack was empty");
57    }
58}