lilium_transcript/
params.rs1use 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 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}