From 34808ccf744f39a345edef3af824ac0bfe666180 Mon Sep 17 00:00:00 2001 From: davidemazzocchi Date: Tue, 11 Nov 2025 16:30:58 +0100 Subject: [PATCH] feat: allow predicate to generate an error and return it boxed --- .../heave/src/imp/catalog_for_each_mut.rs | 4 ++-- 01.workspace/heave/src/str/failed_to.rs | 24 ++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/01.workspace/heave/src/imp/catalog_for_each_mut.rs b/01.workspace/heave/src/imp/catalog_for_each_mut.rs index de4820d..0eaa000 100644 --- a/01.workspace/heave/src/imp/catalog_for_each_mut.rs +++ b/01.workspace/heave/src/imp/catalog_for_each_mut.rs @@ -4,14 +4,14 @@ impl Catalog { pub fn for_each_mut(&self, mut predicate: F) -> Result<(), FailedTo> where T: EAV, - F: FnMut(&mut T), + F: FnMut(&mut T) -> Result<(), Box>, { self.on_items(|items| { for entity in items.values_mut() { let original_item = T::try_from(entity.clone()).map_err(|_| FailedTo::ConvertEntity)?; let mut item = T::try_from(entity.clone()).map_err(|_| FailedTo::ConvertEntity)?; - predicate(&mut item); + predicate(&mut item).map_err(FailedTo::ExecutePredicate)?; if item != original_item { *entity = T::try_into(item).map_err(|_| FailedTo::ConvertObject)?; entity.state = EntityState::Updated; diff --git a/01.workspace/heave/src/str/failed_to.rs b/01.workspace/heave/src/str/failed_to.rs index e8aced3..607939a 100644 --- a/01.workspace/heave/src/str/failed_to.rs +++ b/01.workspace/heave/src/str/failed_to.rs @@ -1,7 +1,7 @@ use crate::*; /// Represents the possible failures that can occur in the library. -#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)] +#[derive(Debug)] pub enum FailedTo { /// Failed to compose filter statement ComposeFilter, @@ -11,6 +11,8 @@ pub enum FailedTo { ConvertObject, /// Failed to convert from Value to type. ConvertValue, + /// Failed to execute predicate to mutate an item. + ExecutePredicate(Box), /// Failed to initialize the database. InitDatabase, /// Failed to load data from the database. @@ -27,6 +29,26 @@ pub enum FailedTo { SQLite(sqlite::FailedTo), } +impl PartialEq for FailedTo { + fn eq(&self, other: &FailedTo) -> bool { + matches!( + (self, other), + (FailedTo::ComposeFilter, FailedTo::ComposeFilter) + | (FailedTo::ConvertEntity, FailedTo::ConvertEntity) + | (FailedTo::ConvertObject, FailedTo::ConvertObject) + | (FailedTo::ConvertValue, FailedTo::ConvertValue) + | (FailedTo::ExecutePredicate(_), FailedTo::ExecutePredicate(_)) + | (FailedTo::InitDatabase, FailedTo::InitDatabase) + | (FailedTo::LoadFromDB, FailedTo::LoadFromDB) + | (FailedTo::LockCatalog, FailedTo::LockCatalog) + | (FailedTo::MapAttribute, FailedTo::MapAttribute) + | (FailedTo::MapEntity, FailedTo::MapEntity) + | (FailedTo::PersistCatalog, FailedTo::PersistCatalog) + | (FailedTo::SQLite(_), FailedTo::SQLite(_)) + ) + } +} + impl From for FailedTo { fn from(value: sqlite::FailedTo) -> Self { Self::SQLite(value)