1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use serde::Deserialize;
use crate::SectionLike;
#[derive(Debug)]
pub struct SectionTower<S> {
sections: Vec<S>,
map: Vec<Option<usize>>,
y_min: isize,
y_max: isize,
}
impl<S> SectionTower<S> {
pub fn sections(&self) -> &[S] {
&self.sections
}
pub fn get_section_for_y(&self, y: isize) -> Option<&S> {
if y >= self.y_max || y < self.y_min {
return None;
}
let lookup_index = y_to_index(y, self.y_min);
let section_index = *self.map.get(lookup_index as usize)?;
self.sections.get(section_index?)
}
pub fn y_min(&self) -> isize {
self.y_min
}
pub fn y_max(&self) -> isize {
self.y_max
}
}
impl<'de, S: SectionLike + Deserialize<'de>> Deserialize<'de> for SectionTower<S> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let sections: Vec<S> = Deserialize::deserialize(deserializer)?;
if sections.is_empty() {
return Ok(Self {
sections,
map: vec![],
y_min: 0,
y_max: 0,
});
}
let lowest_section = sections
.iter()
.min_by_key(|s| s.y())
.expect("checked no empty above");
let null_term = lowest_section.is_terminator();
let min = if null_term {
lowest_section.y() as isize + 1
} else {
lowest_section.y() as isize
};
let max = sections
.iter()
.max_by_key(|s| s.y())
.map(|s| s.y())
.unwrap() as isize;
let mut sparse_sections = vec![None; (1 + max - min) as usize];
for (i, sec) in sections.iter().enumerate() {
if sec.y() == lowest_section.y() && null_term {
continue;
}
let sec_index = (sec.y() as isize - min) as usize;
sparse_sections[sec_index] = Some(i);
}
Ok(Self {
sections,
map: sparse_sections,
y_min: 16 * min,
y_max: 16 * (max + 1),
})
}
}
const fn y_to_index(y: isize, y_min: isize) -> u8 {
((y - y_min) >> 4) as u8
}