steel_core/worldgen/feature/
vanilla_collections.rs1use super::prelude::*;
2
3#[derive(Default)]
9pub(super) struct JavaBlockPosSet {
10 entries: Vec<BlockPos>,
11 present: FxHashSet<BlockPos>,
12}
13
14impl JavaBlockPosSet {
15 pub(super) fn insert(&mut self, pos: BlockPos) -> bool {
16 if !self.present.insert(pos) {
17 return false;
18 }
19
20 self.entries.push(pos);
21 true
22 }
23
24 pub(super) fn remove(&mut self, pos: BlockPos) -> bool {
25 if !self.present.remove(&pos) {
26 return false;
27 }
28
29 self.entries.retain(|entry| *entry != pos);
30 true
31 }
32
33 pub(super) fn contains(&self, pos: BlockPos) -> bool {
34 self.present.contains(&pos)
35 }
36
37 pub(super) fn is_empty(&self) -> bool {
38 self.present.is_empty()
39 }
40
41 pub(super) fn insertion_order(&self) -> impl Iterator<Item = &BlockPos> {
42 self.entries
43 .iter()
44 .filter(|pos| self.present.contains(*pos))
45 }
46
47 pub(super) fn java_ordered_positions(&self) -> Vec<BlockPos> {
48 self.insertion_order().copied().collect()
49 }
50
51 pub(super) fn pop_java_ordered_position(&mut self) -> Option<BlockPos> {
52 let pos = self.java_ordered_positions().into_iter().next()?;
53 self.remove(pos);
54 Some(pos)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn duplicate_positions_keep_first_insertion() {
64 let mut set = JavaBlockPosSet::default();
65 assert!(set.insert(BlockPos::new(1, 2, 3)));
66 assert!(!set.insert(BlockPos::new(1, 2, 3)));
67 assert_eq!(set.java_ordered_positions(), [BlockPos::new(1, 2, 3)]);
68 }
69
70 #[test]
71 fn removed_positions_do_not_iterate() {
72 let mut set = JavaBlockPosSet::default();
73 for x in 0..4 {
74 assert!(set.insert(BlockPos::new(x, 0, 0)));
75 }
76
77 assert!(set.remove(BlockPos::new(1, 0, 0)));
78
79 assert_eq!(
80 set.java_ordered_positions(),
81 [
82 BlockPos::new(0, 0, 0),
83 BlockPos::new(2, 0, 0),
84 BlockPos::new(3, 0, 0)
85 ]
86 );
87 }
88
89 #[test]
90 fn reinserted_position_uses_new_insertion_position() {
91 let mut set = JavaBlockPosSet::default();
92 let first = BlockPos::new(1, 0, 0);
93 let second = BlockPos::new(17, 0, 0);
94
95 assert!(set.insert(first));
96 assert!(set.insert(second));
97 assert!(set.remove(first));
98 assert!(set.insert(first));
99
100 assert_eq!(set.java_ordered_positions(), [second, first]);
101 }
102
103 #[test]
104 fn pop_uses_insertion_order() {
105 let mut set = JavaBlockPosSet::default();
106 let first = BlockPos::new(1, 0, 0);
107 let second = BlockPos::new(2, 0, 0);
108 assert!(set.insert(first));
109 assert!(set.insert(second));
110
111 assert_eq!(set.pop_java_ordered_position(), Some(first));
112 assert_eq!(set.pop_java_ordered_position(), Some(second));
113 assert_eq!(set.pop_java_ordered_position(), None);
114 }
115}