aboutsummaryrefslogtreecommitdiff
path: root/rprt-engine/src/selection.rs
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2025-10-21 20:36:01 +0100
committertslil <tslil@posteo.de>2025-10-21 21:54:56 +0100
commit9f3e21628231f3fa91ab8ff45872a76e7e11fcc4 (patch)
treedd631d501a4f5eba47dac439879a9e8628556468 /rprt-engine/src/selection.rs
parentcaf3cbdd94ec8341f3233bb31c04c72f99502ed9 (diff)
Having a time with passing functions around, really feels like i'm fighting the language
Diffstat (limited to 'rprt-engine/src/selection.rs')
-rw-r--r--rprt-engine/src/selection.rs98
1 files changed, 61 insertions, 37 deletions
diff --git a/rprt-engine/src/selection.rs b/rprt-engine/src/selection.rs
index 9e59ba5..c15512d 100644
--- a/rprt-engine/src/selection.rs
+++ b/rprt-engine/src/selection.rs
@@ -1,8 +1,8 @@
use crate::buffer::BufferID;
-use either::Either;
use std::collections::HashMap;
use std::collections::HashSet;
use std::fmt::Display;
+use thiserror::Error;
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)]
pub enum Rank {
@@ -23,21 +23,12 @@ impl Display for Rank {
}
}
-#[derive(Debug)]
+#[derive(Error, Debug)]
pub enum SelectionError {
+ #[error("Cannnot change selection of {from} to {to}")]
InvalidPromotion { from: Rank, to: Rank },
}
-impl std::fmt::Display for SelectionError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- SelectionError::InvalidPromotion { from, to } => {
- write!(f, "Cannot change selection of {} to {}", from, to)
- }
- }
- }
-}
-
#[derive(Debug, Clone)]
pub struct Interval {
pub start: usize,
@@ -70,6 +61,29 @@ pub enum Selection {
},
}
+// rust is stupid and i have to make a wrapper class and worse still _other
+// people_ have to deal with my wrapper class!
+#[derive(Error, Debug)]
+pub enum VectoriseError<E>
+where
+ E: std::error::Error + 'static,
+{
+ #[error("An error occurred during processing: {0}")]
+ ProcessingError(E),
+
+ #[error("A selection error occurred: {0}")]
+ SelectionError(SelectionError),
+}
+
+impl<E> From<E> for VectoriseError<E>
+where
+ E: std::error::Error + 'static,
+{
+ fn from(e: E) -> Self {
+ VectoriseError::ProcessingError(e)
+ }
+}
+
impl Selection {
pub fn empty() -> Self {
Self::MultiRanges {
@@ -257,32 +271,42 @@ impl Selection {
}
}
- pub fn vectorise<E>(
- &self,
- fn_rank_zero: &impl Fn(&BufferID, &usize) -> Result<Self, E>,
- fn_rank_one: &impl Fn(&BufferID, &Interval) -> Result<Self, E>,
- ) -> Result<Self, Either<E, SelectionError>> {
- let do_rank_one = |b: &usize, rs: &Vec<Interval>| {
- rs.iter()
- .map(|int| fn_rank_one(b, int).map_err(Either::Left))
- .collect::<Result<_, _>>()
- };
+ pub fn vectorise<S, E>(
+ fn_rank_zero: impl Fn(&S, &BufferID, usize) -> Result<Selection, E> + 'static,
+ fn_rank_one: impl Fn(&S, &BufferID, &Interval) -> Result<Selection, E> + 'static,
+ ) -> impl Fn(&S, &Selection) -> Result<Selection, VectoriseError<E>>
+ where
+ E: std::error::Error + 'static,
+ {
+ // look at this mess!
+ use VectoriseError::{ProcessingError, SelectionError};
+ move |state: &S, selection: &Selection| {
+ let do_rank_one = |b: &usize, rs: &Vec<Interval>| {
+ rs.iter()
+ .map(|int| fn_rank_one(state, b, int).map_err(ProcessingError))
+ .collect::<Result<_, _>>()
+ };
- match self {
- Self::Position { buffer, pos } => fn_rank_zero(buffer, pos).map_err(Either::Left),
- Self::Range { buffer, interval } => fn_rank_one(buffer, interval).map_err(Either::Left),
- Self::Ranges { buffer, ranges } => {
- let results = do_rank_one(buffer, ranges)?;
- Self::union(results).map_err(Either::Right)
- }
- Self::MultiRanges { multi_ranges } => {
- let all_ok: Vec<Vec<Self>> = multi_ranges
- .iter()
- .map(|(buffer, ranges)| do_rank_one(buffer, ranges))
- .collect::<Result<_, _>>()?;
- // It would seem that Rust has no built in monadic flatten, or in general cannot lift things to operate on Result... :(
- let results: Vec<Self> = all_ok.into_iter().flatten().collect();
- Self::union(results).map_err(Either::Right)
+ match selection {
+ Self::Position { buffer, pos } => {
+ fn_rank_zero(state, buffer, *pos).map_err(ProcessingError)
+ }
+ Self::Range { buffer, interval } => {
+ fn_rank_one(state, buffer, interval).map_err(VectoriseError::ProcessingError)
+ }
+ Self::Ranges { buffer, ranges } => {
+ let results = do_rank_one(buffer, ranges)?;
+ Self::union(results).map_err(SelectionError)
+ }
+ Self::MultiRanges { multi_ranges } => {
+ let all_ok: Vec<Vec<Self>> = multi_ranges
+ .iter()
+ .map(|(buffer, ranges)| do_rank_one(buffer, ranges))
+ .collect::<Result<_, _>>()?;
+ // It would seem that Rust has no built in monadic flatten, or in general cannot lift things to operate on Result... :(
+ let results: Vec<Self> = all_ok.into_iter().flatten().collect();
+ Self::union(results).map_err(SelectionError)
+ }
}
}
}