duskphantom_utils/
frame_map.rs

1// Copyright 2024 Duskphantom Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17use std::{collections::HashMap, hash::Hash};
18
19pub enum FrameMap<'a, K, V> {
20    Root(HashMap<K, V>),
21    Leaf(HashMap<K, V>, &'a FrameMap<'a, K, V>),
22}
23
24impl<K, V> Default for FrameMap<'_, K, V> {
25    fn default() -> Self {
26        Self::Root(HashMap::new())
27    }
28}
29
30impl<'a, K, V> FrameMap<'a, K, V>
31where
32    K: Eq + Hash,
33{
34    /// Create a new FrameMap.
35    pub fn new() -> Self {
36        Self::default()
37    }
38
39    /// Get the last frame.
40    pub fn last_frame(&mut self) -> &mut HashMap<K, V> {
41        match self {
42            Self::Root(map) => map,
43            Self::Leaf(map, _) => map,
44        }
45    }
46
47    /// Insert a new element into the last frame.
48    pub fn insert(&mut self, k: K, v: V) {
49        self.last_frame().insert(k, v);
50    }
51
52    /// Get an element from all frames.
53    pub fn get(&self, k: &K) -> Option<&V> {
54        let mut map = self;
55        loop {
56            match map {
57                Self::Root(m) => return m.get(k),
58                Self::Leaf(m, parent) => {
59                    if let Some(v) = m.get(k) {
60                        return Some(v);
61                    }
62                    map = parent;
63                }
64            }
65        }
66    }
67
68    /// Make a branch on the frame map.
69    /// Modifications on the new branch will not affect the original one.
70    /// This is useful when implementing scopes.
71    pub fn branch(&'a self) -> Self {
72        Self::Leaf(HashMap::new(), self)
73    }
74}