summaryrefslogtreecommitdiff
path: root/engine/src/lazysort.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/lazysort.rs')
-rw-r--r--engine/src/lazysort.rs79
1 files changed, 79 insertions, 0 deletions
diff --git a/engine/src/lazysort.rs b/engine/src/lazysort.rs
new file mode 100644
index 0000000..e2d6a3f
--- /dev/null
+++ b/engine/src/lazysort.rs
@@ -0,0 +1,79 @@
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct LazySort<T, F: Fn(&T) -> R, R: Ord> {
+ collection: Box<[T]>,
+ sorted: usize,
+ sort_by: F,
+}
+
+pub struct LazySortIter<T, F: Fn(&T) -> R, R: Ord> {
+ sorter: LazySort<T, F, R>,
+ index: usize,
+}
+
+impl<T, F: Fn(&T) -> R, R: Ord> LazySort<T, F, R> {
+ pub fn new(collection: Box<[T]>, sort_by: F) -> Self {
+ Self {
+ collection,
+ sort_by,
+ sorted: 0,
+ }
+ }
+
+ fn len(&self) -> usize {
+ self.collection.len()
+ }
+
+ fn sort(&mut self, index: usize) {
+ let mut min: Option<R> = None;
+ let mut min_index = None;
+ for i in index..self.collection.len() {
+ if let Some(min) = &mut min {
+ let res = (self.sort_by)(&self.collection[i]);
+ if res < *min {
+ *min = res;
+ min_index = Some(i);
+ }
+ }
+ }
+
+ if let Some(min_index) = min_index {
+ self.collection.swap(index, min_index);
+ }
+ }
+
+ fn sort_between(&mut self, start: usize, end: usize) {
+ for i in start..=end {
+ self.sort(i);
+ }
+ }
+
+ pub fn get(&mut self, index: usize) -> Option<&T> {
+ if index >= self.sorted {
+ self.sort_between(self.sorted, index)
+ }
+
+ self.collection.get(index)
+ }
+}
+
+impl<T: Copy, F: Fn(&T) -> R, R: Ord> IntoIterator for LazySort<T, F, R> {
+ type IntoIter = LazySortIter<T, F, R>;
+ type Item = T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ LazySortIter {
+ sorter: self,
+ index: 0,
+ }
+ }
+}
+
+impl<T: Copy, F: Fn(&T) -> R, R: Ord> Iterator for LazySortIter<T, F, R> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let r = self.sorter.get(self.index);
+ self.index += 1;
+ r.cloned()
+ }
+}