use std::slice::Iter;
use rayon::prelude::*;
pub struct ResourcePartInfo {
pub positives: Option<String>,
pub negatives: Option<String>,
pub effects: Option<String>,
}
pub trait SearchablePart {
fn name(&self) -> &str;
fn info(&self) -> &ResourcePartInfo;
}
pub trait SearchableCategorizedParts {
type PartType: SearchablePart + Sync;
fn category(&self) -> &str;
fn parts(&self) -> Iter<Self::PartType>;
}
pub fn filter_parts<'a, T>(
search_query: &str,
parts: &'a Vec<T>,
) -> Vec<&'a <T as SearchableCategorizedParts>::PartType>
where
&'a Vec<T>: IntoParallelIterator,
<&'a Vec<T> as IntoParallelIterator>::Item: SearchableCategorizedParts,
T: SearchableCategorizedParts,
Vec<&'a <T as SearchableCategorizedParts>::PartType>: FromIterator<
&'a <<&'a Vec<T> as IntoParallelIterator>::Item as SearchableCategorizedParts>::PartType,
>,
{
let search_query = search_query.trim().to_lowercase();
parts
.par_iter()
.map(|cat_p: <&'a Vec<T> as IntoParallelIterator>::Item| {
if cat_p.category().to_lowercase().contains(&search_query) {
cat_p
.parts()
.collect::<Vec<&'a <T as SearchableCategorizedParts>::PartType>>()
} else {
cat_p
.parts()
.filter(|p| {
p.name().to_lowercase().contains(&search_query)
|| p.info()
.positives
.iter()
.any(|p| p.to_lowercase().contains(&search_query))
|| p.info()
.negatives
.iter()
.any(|p| p.to_lowercase().contains(&search_query))
|| p.info()
.effects
.iter()
.any(|p| p.to_lowercase().contains(&search_query))
})
.collect::<Vec<&'a <T as SearchableCategorizedParts>::PartType>>()
}
})
.flatten()
.collect::<Vec<_>>()
}
fn main() {
}
I think the compiler is unable to reason with the abstract Item
, maybe for variance or something, but it works if you restrict this to a "normal" &Vec<T>
iterator:
where
&'a Vec<T>: IntoParallelIterator<Item = &'a T>,
&'a T: SearchableCategorizedParts,
// etc
You could even remove the IntoParallelIterator
constraint altogether and just use T: Sync
.
Thanks for your help, I got this working by changing the function to the code below:
pub fn filter_parts<'a, T>(
search_query: &str,
parts: &'a Vec<T>,
) -> Vec<&'a <T as SearchableCategorizedParts>::PartType>
where
T: SearchableCategorizedParts + Sync,
{
let search_query = search_query.trim().to_lowercase();
parts
.into_par_iter()
.map(|cat_p| {
if cat_p.category().to_lowercase().contains(&search_query) {
cat_p
.parts()
.collect::<Vec<_>>()
} else {
cat_p
.parts()
.filter(|p| {
p.name().to_lowercase().contains(&search_query)
|| p.info()
.positives
.iter()
.any(|p| p.to_lowercase().contains(&search_query))
|| p.info()
.negatives
.iter()
.any(|p| p.to_lowercase().contains(&search_query))
|| p.info()
.effects
.iter()
.any(|p| p.to_lowercase().contains(&search_query))
})
.collect::<Vec<_>>()
}
})
.flatten()
.collect::<Vec<_>>()
}```
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.