diff options
| author | tslil <tslil@posteo.de> | 2025-10-21 20:36:01 +0100 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2025-10-21 21:54:56 +0100 |
| commit | 9f3e21628231f3fa91ab8ff45872a76e7e11fcc4 (patch) | |
| tree | dd631d501a4f5eba47dac439879a9e8628556468 /rprt-engine/src/selection.rs | |
| parent | caf3cbdd94ec8341f3233bb31c04c72f99502ed9 (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.rs | 98 |
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) + } } } } |
