From 0056c5ec438dbba9af40d24fd99c22297263d719 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Sat, 21 Sep 2024 16:15:44 +0200 Subject: [PATCH] IntoIter and FroIter --- .../collector/key_derivation_outcome.rs | 2 +- src/derivation/tests/derivation_tests.rs | 6 +- .../account_recovery_scanning.rs | 38 ++++- ...and_analyze_account_recovery_scan_input.rs | 144 ++++++++++++++++-- .../derivation_and_analysis/input.rs | 12 +- .../is_factor_instances_provider.rs | 4 +- .../is_intermediary_derivation_analyzer.rs | 2 +- .../output/probably_free_factor_instances.rs | 57 +++++++ .../output/recovered_securified_entities.rs | 15 ++ .../output/recovered_unsecurified_entities.rs | 15 ++ .../output/unrecovered_securified_entities.rs | 15 ++ .../virtual_entity_creating_instances.rs | 15 ++ .../factor_instances.rs | 74 +++++++++ src/recovery_securify_cache/mod.rs | 2 + .../pre_derived_keys_cache.rs | 107 ++++++++++++- tests/main.rs | 2 +- 16 files changed, 474 insertions(+), 36 deletions(-) create mode 100644 src/recovery_securify_cache/factor_instances.rs diff --git a/src/derivation/collector/key_derivation_outcome.rs b/src/derivation/collector/key_derivation_outcome.rs index d61a7230..3aba886e 100644 --- a/src/derivation/collector/key_derivation_outcome.rs +++ b/src/derivation/collector/key_derivation_outcome.rs @@ -24,7 +24,7 @@ impl KeyDerivationOutcome { } /// ALL factor instances derived by the KeysCollector - pub fn all_factors(&self) -> IndexSet { + pub fn all_factors(&self) -> FactorInstances { self.factors_by_source .clone() .into_iter() diff --git a/src/derivation/tests/derivation_tests.rs b/src/derivation/tests/derivation_tests.rs index 05e9712e..a78f27d5 100644 --- a/src/derivation/tests/derivation_tests.rs +++ b/src/derivation/tests/derivation_tests.rs @@ -49,7 +49,7 @@ mod key_derivation_tests { ) .unwrap(); let outcome = collector.collect_keys().await; - assert!(outcome.all_factors().is_empty()) + assert!(outcome.all_factors().factor_instances().is_empty()) } mod multi_key { @@ -378,7 +378,7 @@ mod key_derivation_tests { paths ); - assert!(outcome.all_factors().len() > 200); + assert!(outcome.all_factors().factor_instances().len() > 200); assert_eq!( outcome @@ -413,7 +413,7 @@ mod key_derivation_tests { KeysCollector::with(factor_source, network_id, key_kind, entity_kind, key_space); let outcome = collector.collect_keys().await; - let factors = outcome.all_factors(); + let factors = outcome.all_factors().factor_instances(); assert_eq!(factors.len(), 1); let factor = factors.first().unwrap(); assert_eq!( diff --git a/src/recovery_securify_cache/account_recover_scan/account_recovery_scanning.rs b/src/recovery_securify_cache/account_recover_scan/account_recovery_scanning.rs index 5790f4b8..9f3284ef 100644 --- a/src/recovery_securify_cache/account_recover_scan/account_recovery_scanning.rs +++ b/src/recovery_securify_cache/account_recover_scan/account_recovery_scanning.rs @@ -8,16 +8,42 @@ async fn _account_recovery_scan( DerivationAndAnalysisAccountRecoveryScan::try_from(analysis) } -pub async fn account_recovery_scan( +pub async fn onboarding_account_recovery_scan( factor_sources: IndexSet, gateway: Arc, derivation_interactors: Arc, + is_done_query: Arc, ) -> Result { - let analysis = _account_recovery_scan(DeriveAndAnalyzeAccountRecoveryScanInput::new( - factor_sources, - gateway, - derivation_interactors, - )) + let analysis = _account_recovery_scan( + DeriveAndAnalyzeAccountRecoveryScanInput::onboarding_account_recovery_scan( + factor_sources, + gateway, + derivation_interactors, + is_done_query, + ), + ) + .await?; + Ok(AccountRecoveryScanOutcome::from(analysis)) +} + +pub async fn manual_account_recovery_scan( + factor_sources: IndexSet, + gateway: Arc, + cache: impl Into>, + profile: ProfileAnalyzer, + derivation_interactors: Arc, + is_done_query: Arc, +) -> Result { + let analysis = _account_recovery_scan( + DeriveAndAnalyzeAccountRecoveryScanInput::manual_account_recovery_scan( + factor_sources, + gateway, + cache, + profile, + derivation_interactors, + is_done_query, + ), + ) .await?; Ok(AccountRecoveryScanOutcome::from(analysis)) } diff --git a/src/recovery_securify_cache/account_recover_scan/derive_and_analyze_account_recovery_scan_input.rs b/src/recovery_securify_cache/account_recover_scan/derive_and_analyze_account_recovery_scan_input.rs index f885c2d6..26ce05f1 100644 --- a/src/recovery_securify_cache/account_recover_scan/derive_and_analyze_account_recovery_scan_input.rs +++ b/src/recovery_securify_cache/account_recover_scan/derive_and_analyze_account_recovery_scan_input.rs @@ -1,26 +1,143 @@ #![allow(unused)] #![allow(unused_variables)] -use crate::prelude::*; +use crate::{gateway, prelude::*}; +/// Use by OARS (Onboarding Account Recovery Scan) and MARS +/// (Manual Account Recovery Scan). pub struct DeriveAndAnalyzeAccountRecoveryScanInput { factor_sources: IndexSet, gateway: Arc, + + /// Empty for OARS, **maybe** not empty for MARS + cache: PreDerivedKeysCache, + /// Empty for OARS, **guaranteed** not empty for MARS + profile: ProfileAnalyzer, + derivation_interactors: Arc, + is_done_query: Arc, } impl DeriveAndAnalyzeAccountRecoveryScanInput { - pub fn new( + fn new( factor_sources: IndexSet, gateway: Arc, + cache: impl Into>, + profile: impl Into>, derivation_interactors: Arc, + is_done_query: Arc, ) -> Self { Self { factor_sources, gateway, + cache: cache.into().unwrap_or_default(), + profile: profile.into().unwrap_or_default(), + derivation_interactors, + is_done_query, + } + } + + /// OARS + pub fn onboarding_account_recovery_scan( + factor_sources: IndexSet, + gateway: Arc, + derivation_interactors: Arc, + is_done_query: Arc, + ) -> Self { + Self::new( + factor_sources, + gateway, + None, + None, derivation_interactors, + is_done_query, + ) + } + + /// MARS + pub fn manual_account_recovery_scan( + factor_sources: IndexSet, + gateway: Arc, + cache: impl Into>, + profile: ProfileAnalyzer, + derivation_interactors: Arc, + is_done_query: Arc, + ) -> Self { + Self::new( + factor_sources, + gateway, + cache, + profile, + derivation_interactors, + is_done_query, + ) + } +} + +#[derive(Debug, Default)] +pub struct ProfileAnalyzer; + +pub struct FactorInstancesProviderImpl { + cache: PreDerivedKeysCache, + gateway: Option>, + profile: ProfileAnalyzer, +} +impl FactorInstancesProviderImpl { + /// # Panics + /// Panics if all arguments are `None`. + fn new( + cache: impl Into>, + gateway: impl Into>>, + profile: impl Into>, + ) -> Self { + let cache = cache.into(); + let gateway = gateway.into(); + let profile = profile.into(); + assert!( + !(cache.is_none() && gateway.is_none() && profile.is_none()), + "All arguments are None" + ); + Self { + cache: cache.unwrap_or_default(), + gateway, + profile: profile.unwrap_or_default(), } } + + /// OARS + pub fn onboarding_account_recovery_scan(gateway: Arc) -> Self { + Self::new(None, gateway, None) + } + + /// MARS + pub fn manual_account_recovery_scan( + cache: impl Into>, + gateway: Arc, + profile: ProfileAnalyzer, + ) -> Self { + Self::new(cache, gateway, profile) + } +} + +#[async_trait::async_trait] +impl IsFactorInstancesProvider for FactorInstancesProviderImpl { + async fn provide_instances( + &self, + derivation_requests: DerivationRequests, + ) -> Result { + let cache_outcome = self.cache.load(&derivation_requests).await?; + todo!(); + } +} + +#[async_trait::async_trait] +impl IsIntermediaryDerivationAnalyzer for FactorInstancesProviderImpl { + async fn analyze( + &self, + factor_instances: FactorInstances, + ) -> Result { + todo!() + } } impl From for DeriveAndAnalyzeInput { @@ -44,12 +161,13 @@ impl From for DeriveAndAnalyzeInput { .into_iter() .map(move |u| u.derivation_request_with_factor_source_id(factor_source_id)) }) - .collect::>(); + .collect::(); - let factor_instances_provider: Arc = { unreachable!() }; - let analyze_factor_instances: Arc = - { unreachable!() }; - let is_done: Arc = { unreachable!() }; + let analyzing_factor_instance_provider = Arc::new(FactorInstancesProviderImpl::new( + value.cache, + value.gateway, + value.profile, + )); Self::new( value.factor_sources.clone(), @@ -59,9 +177,9 @@ impl From for DeriveAndAnalyzeInput { .map(|f| f.factor_source_id()) .collect(), initial_derivation_requests, - factor_instances_provider, - analyze_factor_instances, - is_done, + analyzing_factor_instance_provider.clone(), + analyzing_factor_instance_provider.clone(), + value.is_done_query, ) } } @@ -76,7 +194,7 @@ pub struct UncachedFactorInstanceProvider { impl UncachedFactorInstanceProvider { fn derivation_paths_for_requests( &self, - derivation_requests: IndexSet, + derivation_requests: DerivationRequests, ) -> IndexMap> { todo!() } @@ -86,8 +204,8 @@ impl UncachedFactorInstanceProvider { impl IsFactorInstancesProvider for UncachedFactorInstanceProvider { async fn provide_instances( &self, - derivation_requests: IndexSet, - ) -> Result> { + derivation_requests: DerivationRequests, + ) -> Result { let derivation_paths = self.derivation_paths_for_requests(derivation_requests); let keys_collector = KeysCollector::new( self.factor_sources.clone(), diff --git a/src/recovery_securify_cache/derivation_and_analysis/input.rs b/src/recovery_securify_cache/derivation_and_analysis/input.rs index 13d80f6d..280cf312 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/input.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/input.rs @@ -11,7 +11,7 @@ pub struct DeriveAndAnalyzeInput { factor_sources: IndexSet, ids_of_new_factor_sources: IndexSet, - next_requests: IndexSet, + next_requests: DerivationRequests, factor_instances_provider: Arc, @@ -27,7 +27,7 @@ impl DeriveAndAnalyzeInput { pub fn new( factor_sources: IndexSet, ids_of_new_factor_sources: IndexSet, - initial_derivation_requests: IndexSet, + initial_derivation_requests: DerivationRequests, factor_instances_provider: Arc, analyze_factor_instances: Arc, is_done: Arc, @@ -54,7 +54,7 @@ impl DeriveAndAnalyzeInput { impl IsIntermediaryDerivationAnalyzer for DeriveAndAnalyzeInput { async fn analyze( &self, - factor_instances: IndexSet, + factor_instances: FactorInstances, ) -> Result { self.analyze_factor_instances .analyze(factor_instances) @@ -70,13 +70,11 @@ impl IsDerivationDoneQuery for DeriveAndAnalyzeInput { } impl DeriveAndAnalyzeInput { - fn next_requests(&self) -> IndexSet { + fn next_requests(&self) -> DerivationRequests { self.next_requests.clone() } - pub async fn load_cached_or_derive_new_instances( - &self, - ) -> Result> { + pub async fn load_cached_or_derive_new_instances(&self) -> Result { let factor_sources = self.all_factor_sources(); let requests = self.next_requests(); let factor_instances = self diff --git a/src/recovery_securify_cache/derivation_and_analysis/is_factor_instances_provider.rs b/src/recovery_securify_cache/derivation_and_analysis/is_factor_instances_provider.rs index b66ad3e7..9e8bae35 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/is_factor_instances_provider.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/is_factor_instances_provider.rs @@ -4,6 +4,6 @@ use crate::prelude::*; pub trait IsFactorInstancesProvider: Sync + Send { async fn provide_instances( &self, - derivation_requests: IndexSet, - ) -> Result>; + derivation_requests: DerivationRequests, + ) -> Result; } diff --git a/src/recovery_securify_cache/derivation_and_analysis/is_intermediary_derivation_analyzer.rs b/src/recovery_securify_cache/derivation_and_analysis/is_intermediary_derivation_analyzer.rs index f4220c62..0e475c1d 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/is_intermediary_derivation_analyzer.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/is_intermediary_derivation_analyzer.rs @@ -6,6 +6,6 @@ use crate::prelude::*; pub trait IsIntermediaryDerivationAnalyzer: Sync + Send { async fn analyze( &self, - factor_instances: IndexSet, + factor_instances: FactorInstances, ) -> Result; } diff --git a/src/recovery_securify_cache/derivation_and_analysis/output/probably_free_factor_instances.rs b/src/recovery_securify_cache/derivation_and_analysis/output/probably_free_factor_instances.rs index d0aee872..f27548bc 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/output/probably_free_factor_instances.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/output/probably_free_factor_instances.rs @@ -1,8 +1,50 @@ use crate::prelude::*; +impl HierarchicalDeterministicFactorInstance { + fn satisfies(&self, request: &DerivationRequest) -> bool { + self.derivation_path().satisfies(request) + && request.factor_source_id == self.factor_source_id + } +} + +impl DerivationPath { + #[allow(clippy::nonminimal_bool)] + fn satisfies(&self, request: &DerivationRequest) -> bool { + request.entity_kind == self.entity_kind + && request.network_id == self.network_id + && request.entity_kind == self.entity_kind + && request.key_kind == self.key_kind + && request.key_space == self.index.key_space() + } +} + +impl DerivationRequests { + pub fn fully_satisfied_by(&self, instances: &dyn IsFactorInstanceCollectionBase) -> bool { + instances.satisfies_all_requests(self) + } + pub fn partially_satisfied_by(&self, instances: &dyn IsFactorInstanceCollectionBase) -> bool { + instances.satisfies_some_requests(self) + } +} + pub trait IsFactorInstanceCollectionBase { fn factor_instances(&self) -> IndexSet; + fn satisfies_all_requests(&self, requests: &DerivationRequests) -> bool { + requests.requests().iter().all(|request| { + self.factor_instances() + .iter() + .any(|instance| instance.satisfies(request)) + }) + } + fn satisfies_some_requests(&self, requests: &DerivationRequests) -> bool { + requests.requests().iter().any(|request| { + self.factor_instances() + .iter() + .any(|instance| instance.satisfies(request)) + }) + } } + pub trait IsFactorInstanceCollection: IsFactorInstanceCollectionBase + HasSampleValues + Sized { @@ -49,6 +91,21 @@ pub struct ProbablyFreeFactorInstances { factor_instances: Vec, } +impl FromIterator for ProbablyFreeFactorInstances { + fn from_iter>(iter: I) -> Self { + Self::new(iter.into_iter().collect()) + } +} + +impl IntoIterator for ProbablyFreeFactorInstances { + type Item = HierarchicalDeterministicFactorInstance; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.factor_instances().into_iter() + } +} + impl IsFactorInstanceCollectionBase for ProbablyFreeFactorInstances { fn factor_instances(&self) -> IndexSet { self.factor_instances.iter().cloned().collect() diff --git a/src/recovery_securify_cache/derivation_and_analysis/output/recovered_securified_entities.rs b/src/recovery_securify_cache/derivation_and_analysis/output/recovered_securified_entities.rs index 81df3a74..a098a5c4 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/output/recovered_securified_entities.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/output/recovered_securified_entities.rs @@ -7,6 +7,21 @@ pub struct RecoveredSecurifiedEntities { securified_entities: Vec, } +impl FromIterator for RecoveredSecurifiedEntities { + fn from_iter>(iter: I) -> Self { + Self::new(iter.into_iter().collect()) + } +} + +impl IntoIterator for RecoveredSecurifiedEntities { + type Item = SecurifiedEntity; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.securified_entities().into_iter() + } +} + impl RecoveredSecurifiedEntities { pub fn new(securified_entities: IndexSet) -> Self { Self { diff --git a/src/recovery_securify_cache/derivation_and_analysis/output/recovered_unsecurified_entities.rs b/src/recovery_securify_cache/derivation_and_analysis/output/recovered_unsecurified_entities.rs index 32b109fc..d284d9f1 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/output/recovered_unsecurified_entities.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/output/recovered_unsecurified_entities.rs @@ -7,6 +7,21 @@ pub struct RecoveredUnsecurifiedEntities { unsecurified_entities: Vec, } +impl FromIterator for RecoveredUnsecurifiedEntities { + fn from_iter>(iter: I) -> Self { + Self::new(iter.into_iter().collect()) + } +} + +impl IntoIterator for RecoveredUnsecurifiedEntities { + type Item = UnsecurifiedEntity; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.unsecurified_entities().into_iter() + } +} + impl RecoveredUnsecurifiedEntities { pub fn new(unsecurified_entities: IndexSet) -> Self { Self { diff --git a/src/recovery_securify_cache/derivation_and_analysis/output/unrecovered_securified_entities.rs b/src/recovery_securify_cache/derivation_and_analysis/output/unrecovered_securified_entities.rs index 8d0308db..65ecb08b 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/output/unrecovered_securified_entities.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/output/unrecovered_securified_entities.rs @@ -10,6 +10,21 @@ pub struct UnrecoveredSecurifiedEntities { entities: Vec, } +impl FromIterator for UnrecoveredSecurifiedEntities { + fn from_iter>(iter: I) -> Self { + Self::new(iter.into_iter().collect()) + } +} + +impl IntoIterator for UnrecoveredSecurifiedEntities { + type Item = UnrecoveredSecurifiedEntity; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.entities().into_iter() + } +} + impl UnrecoveredSecurifiedEntities { pub fn new(entities: IndexSet) -> Self { Self { diff --git a/src/recovery_securify_cache/derivation_and_analysis/output/virtual_entity_creating_instances.rs b/src/recovery_securify_cache/derivation_and_analysis/output/virtual_entity_creating_instances.rs index 8c085101..5b5f5997 100644 --- a/src/recovery_securify_cache/derivation_and_analysis/output/virtual_entity_creating_instances.rs +++ b/src/recovery_securify_cache/derivation_and_analysis/output/virtual_entity_creating_instances.rs @@ -79,6 +79,21 @@ pub struct VirtualEntityCreatingInstances { vecis: Vec, } +impl FromIterator for VirtualEntityCreatingInstances { + fn from_iter>(iter: I) -> Self { + Self::new(iter.into_iter().collect()) + } +} + +impl IntoIterator for VirtualEntityCreatingInstances { + type Item = VirtualEntityCreatingInstance; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.vecis().into_iter() + } +} + impl VirtualEntityCreatingInstances { pub fn new(vecis: IndexSet) -> Self { Self { diff --git a/src/recovery_securify_cache/factor_instances.rs b/src/recovery_securify_cache/factor_instances.rs new file mode 100644 index 00000000..bf30737a --- /dev/null +++ b/src/recovery_securify_cache/factor_instances.rs @@ -0,0 +1,74 @@ +use crate::prelude::*; + +/// A collection of factor instances. +#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)] +pub struct FactorInstances { + factor_instances: Vec, +} + +impl From> for FactorInstances { + fn from(instances: IndexSet) -> Self { + Self::new(instances) + } +} + +impl IntoIterator for FactorInstances { + type Item = HierarchicalDeterministicFactorInstance; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.factor_instances().into_iter() + } +} + +impl FromIterator for FactorInstances { + fn from_iter>(iter: I) -> Self { + Self::new(iter.into_iter().collect()) + } +} + +impl IsFactorInstanceCollectionBase for FactorInstances { + fn factor_instances(&self) -> IndexSet { + self.factor_instances.iter().cloned().collect() + } +} +impl IsFactorInstanceCollection for FactorInstances { + fn new(instances: IndexSet) -> Self { + Self { + factor_instances: instances.into_iter().collect(), + } + } +} + +impl HasSampleValues for FactorInstances { + fn sample() -> Self { + Self::new(IndexSet::from_iter([ + HierarchicalDeterministicFactorInstance::sample(), + HierarchicalDeterministicFactorInstance::sample_other(), + ])) + } + + fn sample_other() -> Self { + Self::new(IndexSet::just( + HierarchicalDeterministicFactorInstance::sample_other(), + )) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + type Sut = FactorInstances; + + #[test] + fn equality() { + assert_eq!(Sut::sample(), Sut::sample()); + assert_eq!(Sut::sample_other(), Sut::sample_other()); + } + + #[test] + fn inequality() { + assert_ne!(Sut::sample(), Sut::sample_other()); + } +} diff --git a/src/recovery_securify_cache/mod.rs b/src/recovery_securify_cache/mod.rs index 70a25751..11b2860e 100644 --- a/src/recovery_securify_cache/mod.rs +++ b/src/recovery_securify_cache/mod.rs @@ -1,9 +1,11 @@ mod account_recover_scan; mod derivation_and_analysis; mod derive_and_analyze; +mod factor_instances; mod pre_derived_keys_cache; pub use account_recover_scan::*; pub use derivation_and_analysis::*; pub use derive_and_analyze::*; +pub use factor_instances::*; pub use pre_derived_keys_cache::*; diff --git a/src/recovery_securify_cache/pre_derived_keys_cache.rs b/src/recovery_securify_cache/pre_derived_keys_cache.rs index d7dd965f..70374b3a 100644 --- a/src/recovery_securify_cache/pre_derived_keys_cache.rs +++ b/src/recovery_securify_cache/pre_derived_keys_cache.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +use crate::{prelude::*, recovery_securify_cache::factor_instances}; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct PreDerivedKeysCache; impl PreDerivedKeysCache { @@ -12,3 +12,106 @@ impl PreDerivedKeysCache { Self } } + +#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] +pub struct DerivationRequests { + hidden: HiddenConstructor, + requests: Vec, +} + +impl FromIterator for DerivationRequests { + fn from_iter>(iter: I) -> Self { + Self::new(iter.into_iter().collect()) + } +} + +impl IntoIterator for DerivationRequests { + type Item = DerivationRequest; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.requests().into_iter() + } +} + +impl DerivationRequests { + pub fn new(requests: IndexSet) -> Self { + Self { + hidden: HiddenConstructor, + requests: requests.into_iter().collect(), + } + } + pub fn requests(&self) -> IndexSet { + self.requests.clone().into_iter().collect() + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct CacheOutcome { + #[allow(dead_code)] + hidden_constructor: HiddenConstructor, + /// The requests + pub requests: DerivationRequests, + /// If the cache has contains more free instances after having satisfied the requests. + pub has_spare_capacity: bool, + pub fully_satisfied: bool, + pub factor_instances: FactorInstances, +} +impl CacheOutcome { + pub fn empty(requests: &DerivationRequests) -> Self { + Self { + hidden_constructor: HiddenConstructor, + requests: requests.clone(), + has_spare_capacity: false, + fully_satisfied: false, + factor_instances: FactorInstances::default(), + } + } + pub fn partial( + requests: &DerivationRequests, + factor_instances: impl Into, + ) -> Self { + let factor_instances = factor_instances.into(); + assert!(requests.partially_satisfied_by(&factor_instances)); + Self { + hidden_constructor: HiddenConstructor, + requests: requests.clone(), + has_spare_capacity: false, + fully_satisfied: false, + factor_instances, + } + } + fn full_specifying_spare_capacity( + has_spare_capacity: bool, + requests: &DerivationRequests, + factor_instances: impl Into, + ) -> Self { + let factor_instances = factor_instances.into(); + assert!(requests.fully_satisfied_by(&factor_instances)); + Self { + hidden_constructor: HiddenConstructor, + requests: requests.clone(), + fully_satisfied: true, + has_spare_capacity, + factor_instances, + } + } + pub fn full_last( + requests: &DerivationRequests, + factor_instances: impl Into, + ) -> Self { + Self::full_specifying_spare_capacity(false, requests, factor_instances) + } + pub fn full_with_spare( + requests: &DerivationRequests, + factor_instances: impl Into, + ) -> Self { + Self::full_specifying_spare_capacity(true, requests, factor_instances) + } +} + +impl PreDerivedKeysCache { + pub async fn load(&self, _requests: &DerivationRequests) -> Result { + todo!() + } +} diff --git a/tests/main.rs b/tests/main.rs index 152f2660..b76ef6b9 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -120,7 +120,7 @@ mod integration_test_derivation { .unwrap(); let outcome = collector.collect_keys().await; - let factors = outcome.all_factors(); + let factors = outcome.all_factors().factor_instances(); assert_eq!( factors.len(), paths