Skip to main content

lilium_transcript/
params.rs

1use std::{
2    any::{type_name, Any, TypeId},
3    collections::{btree_map::Entry, BTreeMap},
4};
5
6#[derive(Default, Debug)]
7pub struct ParamResolver {
8    map: BTreeMap<TypeId, usize>,
9}
10
11impl ParamResolver {
12    pub fn new() -> Self {
13        Self {
14            map: BTreeMap::new(),
15        }
16    }
17
18    /// Sets the given param to the given value, trying to a set second value
19    /// for the same type will panic.
20    pub fn set<T: Any>(mut self, value: usize) -> Self {
21        let id = TypeId::of::<T>();
22        match self.map.entry(id) {
23            Entry::Vacant(e) => {
24                e.insert(value);
25            }
26            Entry::Occupied(e) => {
27                if &value != e.get() {
28                    panic!(
29                        "Tried to set param {} to {} when {} was already set",
30                        type_name::<T>(),
31                        value,
32                        e.get()
33                    );
34                }
35            }
36        }
37        self
38    }
39
40    pub fn get<T: Any>(&self) -> usize {
41        let id = TypeId::of::<T>();
42        match self.map.get(&id) {
43            Some(value) => *value,
44            None => {
45                panic!("param not present: {}", type_name::<T>());
46            }
47        }
48    }
49
50    fn try_get<T: Any>(&self) -> Option<usize> {
51        let id = TypeId::of::<T>();
52        self.map.get(&id).cloned()
53    }
54}
55
56#[derive(Default, Debug)]
57pub struct ParamStack {
58    frames: Vec<ParamResolver>,
59}
60
61impl ParamStack {
62    pub fn new(frames: Vec<ParamResolver>) -> Self {
63        Self { frames }
64    }
65
66    pub fn get<T: Any>(&self) -> usize {
67        if self.frames.is_empty() {
68            panic!("param get() called on an empty stack");
69        }
70        for frame in self.frames.iter().rev() {
71            if let Some(param) = frame.try_get::<T>() {
72                return param;
73            }
74        }
75        panic!("param {} not set in any frame", type_name::<T>());
76    }
77
78    pub fn push(&mut self, frame: ParamResolver) {
79        self.frames.push(frame);
80    }
81
82    pub fn pop(&mut self) {
83        if self.frames.pop().is_none() {
84            panic!("param pop() called in empty stack");
85        }
86    }
87
88    pub fn top(&self) -> &ParamResolver {
89        self.frames.last().unwrap()
90    }
91}