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}