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}