pub trait Apply: Sized {
fn apply<F>(mut self, block: F) -> Self
where
F: FnOnce(&mut Self),
{
block(&mut self);
self
}
}
impl<T> Apply for T {}
pub trait Run {
fn run<R, F>(self, block: F) -> R
where
F: FnOnce(Self) -> R,
Self: Sized;
}
impl<T> Run for T {
fn run<R, F>(self, block: F) -> R
where
F: FnOnce(Self) -> R,
Self: Sized,
{
block(self)
}
}
pub trait TakeIf: Sized {
fn take_if<F>(self, predicate: F) -> Option<Self>
where
F: FnOnce(&Self) -> bool;
}
impl<T> TakeIf for T {
fn take_if<F>(self, predicate: F) -> Option<Self>
where
F: FnOnce(&Self) -> bool,
{
if predicate(&self) {
Some(self)
} else {
None
}
}
}
pub trait TakeUnless: Sized {
fn take_unless<F>(self, predicate: F) -> Option<Self>
where
F: FnOnce(&Self) -> bool;
}
impl<T> TakeUnless for T {
fn take_unless<F>(self, predicate: F) -> Option<Self>
where
F: FnOnce(&Self) -> bool,
{
if !predicate(&self) {
Some(self)
} else {
None
}
}
}
pub fn repeat<F>(times: usize, mut action: F)
where
F: FnMut(usize),
{
for index in 0..times {
action(index);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_apply_trait() {
let value = 0;
let new_value = value
.apply(|v| {
assert_eq!(*v, 0);
*v += 1;
})
.apply(|v| {
assert_eq!(*v, 1);
});
assert_eq!(value, 0);
assert_eq!(new_value, 1);
}
#[test]
fn test_run_trait() {
let value = vec![0];
let new_value = value
.clone()
.run(|v| {
assert_eq!(v, vec![0]);
let first_item_edited = *v.first().unwrap() + 1;
assert_eq!(first_item_edited, 1);
first_item_edited
})
.run(|v| {
assert_eq!(v, 1);
let v_str = format!("{}", v);
assert_eq!(v_str, "1");
v_str
});
assert_eq!(value.clone(), vec![0]);
assert_eq!(new_value, "1");
}
#[test]
fn test_take_if_trait() {
let value = 10;
let result = value.take_if(|&v| v > 5);
assert_eq!(result, Some(10));
let result = value.take_if(|&v| v < 5);
assert_eq!(result, None);
}
#[test]
fn test_take_unless_trait() {
let value = 10;
let result = value.take_unless(|&v| v > 5);
assert_eq!(result, None);
let result = value.take_unless(|&v| v < 5);
assert_eq!(result, Some(10));
}
#[test]
fn test_repeat_function() {
let mut sum = 0;
repeat(5, |index| {
sum += index;
});
assert_eq!(sum, 10); }
}