Skip to content

Instantly share code, notes, and snippets.

@elycruz
Last active April 29, 2023 03:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elycruz/58ba206e027b77996ba27461113a6bbb to your computer and use it in GitHub Desktop.
Save elycruz/58ba206e027b77996ba27461113a6bbb to your computer and use it in GitHub Desktop.
Single threaded "filters" pattern
/**
* Single threaded "filters" patterns.
*/
use std::borrow::{Cow, Cow::*};
pub type Filter<'a, T> = &'a dyn Fn(Cow<'a, T>) -> Cow<'a, T>;
fn filter<'a>(filters: &'a [Filter<'a, str>], value: Cow<'a, str>) -> Cow<'a, str> {
filters.iter().rfold(value, |agg, f| f(agg))
}
fn to_uppercase(s: Cow<str>) -> Cow<str> {
Owned(s.to_uppercase())
}
fn vowels_only(s: Cow<str>) -> Cow<str> {
Owned(String::from_iter(
s.chars()
.filter(|c| "aeiou".contains::<&str>(&c.to_string()))
.collect::<Vec<char>>()
.iter(),
))
}
#[derive(Clone)]
struct WithCow<'a, T: ?Sized + ToOwned> {
value: Option<Cow<'a, T>>,
filters: Option<&'a [Filter<'a, T>]>,
}
impl<'a, T: ?Sized + ToOwned> WithCow<'a, T> {
pub fn new(value: Option<Cow<'a, T>>, filters: Option<&'a [Filter<'a, T>]>) -> Self {
WithCow { value, filters }
}
pub fn filter(&mut self) -> &Self {
let value = self
.filters
.as_ref()
.zip(self.value.as_ref())
.map(|(filters, value)| {
filters
.iter()
.rfold(value.clone(), |agg, f: &Filter<'a, T>| -> Cow<T> { f(agg) })
});
if value.is_some() {
self.value = value;
}
self
}
}
fn main() {
let filters: Vec<Filter<str>> = vec![&to_uppercase, &vowels_only];
let squared = |x: Cow<usize>| Owned(x.pow(2));
let usize_filters: Vec<Filter<usize>> = vec![&squared, &squared];
let mut with_cow =
WithCow::<str>::new(Some(Owned("hello-world".to_string())), Some(&filters));
let mut with_usize_cow = WithCow::<usize>::new(Some(Owned(2)), Some(&usize_filters));
println!("Results:\n\n{:?}", filter(&filters, "hello-world".into()));
println!("{:?}", &with_cow.filter().value);
println!("{:?}", &with_usize_cow.filter().value);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment