1use std::cmp::{max, Ordering};
2use std::collections::{BTreeMap, HashMap};
3use std::fmt::{Display, Error, Formatter};
4use std::ops::{Add, Sub};
5
6pub type LevelType = u32;
7
8#[derive(Debug, Copy, Clone, Ord, Eq, PartialEq)]
10pub enum Level {
11 Omega,
12 Num(LevelType),
13}
14
15impl Level {
16 pub fn max(self, other: Self) -> Self {
17 use Level::*;
18 match (self, other) {
19 (Num(a), Num(b)) => Num(max(a, b)),
20 _ => Omega,
21 }
22 }
23
24 pub fn map(self, f: impl FnOnce(LevelType) -> LevelType) -> Self {
25 self.and_then(|a| Level::Num(f(a)))
26 }
27
28 pub fn and_then(self, f: impl FnOnce(LevelType) -> Self) -> Self {
29 use Level::*;
30 match self {
31 Omega => Omega,
32 Num(n) => f(n),
33 }
34 }
35}
36
37pub type LevelCalcState = Option<Level>;
43
44pub trait LiftEx: Sized {
46 fn lift(self, levels: LevelType) -> Self;
48
49 fn fall(self, levels: u32) -> Self;
53
54 fn calc_level(&self) -> LevelCalcState;
56
57 fn level(&self) -> Level {
61 self.calc_level().unwrap_or_default()
62 }
63}
64
65impl From<LevelType> for Level {
66 fn from(n: LevelType) -> Self {
67 Level::Num(n)
68 }
69}
70
71impl From<usize> for Level {
72 fn from(n: usize) -> Self {
73 From::from(n as LevelType)
74 }
75}
76
77impl Display for Level {
78 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
79 match self {
80 Level::Omega => f.write_str("\u{03C9}"),
81 Level::Num(n) => n.fmt(f),
82 }
83 }
84}
85
86impl Default for Level {
87 fn default() -> Self {
88 From::from(0 as LevelType)
89 }
90}
91
92impl PartialOrd for Level {
93 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
94 use Level::*;
95 match (self, other) {
96 (Omega, Omega) => Some(Ordering::Equal),
97 (Omega, Num(..)) => Some(Ordering::Greater),
98 (Num(..), Omega) => Some(Ordering::Less),
99 (Num(a), Num(b)) => a.partial_cmp(b),
100 }
101 }
102}
103
104impl Add for Level {
105 type Output = Self;
106
107 fn add(self, rhs: Self) -> Self::Output {
108 use Level::*;
109 match (self, rhs) {
110 (Num(a), Num(b)) => Num(a + b),
111 _ => Omega,
112 }
113 }
114}
115
116impl Add<LevelType> for Level {
117 type Output = Self;
118
119 fn add(self, rhs: LevelType) -> Self::Output {
120 self.map(|a| a + rhs)
121 }
122}
123
124impl Sub<LevelType> for Level {
125 type Output = Self;
126
127 fn sub(self, rhs: LevelType) -> Self::Output {
128 self.map(|a| a - rhs)
129 }
130}
131
132pub fn lift_tree_map<T: LiftEx>(
133 levels: LevelType,
134 map: BTreeMap<String, T>,
135) -> BTreeMap<String, T> {
136 map.into_iter()
137 .map(|(name, e)| (name, e.lift(levels)))
138 .collect()
139}
140
141pub fn lift_hash_map<T: LiftEx>(levels: LevelType, map: HashMap<String, T>) -> HashMap<String, T> {
142 map.into_iter()
143 .map(|(name, e)| (name, e.lift(levels)))
144 .collect()
145}
146
147pub fn fall_tree_map<T: LiftEx>(levels: u32, map: BTreeMap<String, T>) -> BTreeMap<String, T> {
148 map.into_iter()
149 .map(|(name, e)| (name, e.fall(levels)))
150 .collect()
151}
152
153pub fn fall_hash_map<T: LiftEx>(levels: u32, map: HashMap<String, T>) -> HashMap<String, T> {
154 map.into_iter()
155 .map(|(name, e)| (name, e.fall(levels)))
156 .collect()
157}
158
159pub fn calc_tree_map_level(map: &BTreeMap<String, impl LiftEx>) -> LevelCalcState {
160 let levels: Option<Vec<_>> = map.values().map(LiftEx::calc_level).collect();
161 Some(levels?.into_iter().max().unwrap_or_default())
162}
163
164pub fn calc_tree_map_plus_one_level(
165 one: &impl LiftEx,
166 map: &BTreeMap<String, impl LiftEx>,
167) -> LevelCalcState {
168 let levels: Option<Vec<_>> = map.values().map(LiftEx::calc_level).collect();
169 let level = levels?.into_iter().max().unwrap_or_default();
170 Some(one.calc_level()?.max(level))
171}
172
173pub fn calc_slice_level(vec: &[impl LiftEx]) -> LevelCalcState {
174 let levels: Option<Vec<_>> = vec.iter().map(LiftEx::calc_level).collect();
175 Some(levels?.into_iter().max().unwrap_or_default())
176}
177
178pub fn calc_slice_plus_one_level(one: &impl LiftEx, vec: &[impl LiftEx]) -> LevelCalcState {
179 let levels: Option<Vec<_>> = vec.iter().map(LiftEx::calc_level).collect();
180 let level = levels?.into_iter().max().unwrap_or_default();
181 Some(one.calc_level()?.max(level))
182}
183
184pub fn calc_hash_map_level(map: &HashMap<String, impl LiftEx>) -> LevelCalcState {
185 let levels: Option<Vec<_>> = map.values().map(LiftEx::calc_level).collect();
186 Some(levels?.into_iter().max().unwrap_or_default())
187}