sweet_utils/utils/
pipeline.rs

1/// Basically a `FnOnce` trait, but not nightly and a little less awkward to implement.
2pub trait Pipeline<In, Out = In> {
3	/// Consume self and apply to the target
4	fn apply(self, value: In) -> Out;
5}
6
7impl<F, In, Out> Pipeline<In, Out> for F
8where
9	F: FnOnce(In) -> Out,
10{
11	fn apply(self, value: In) -> Out { self(value) }
12}
13
14
15/// Utilities for method-chaining on any type.
16/// Very similar in its goals to [`tap`](https://crates.io/crates/tap)
17pub trait PipelineTarget: Sized {
18	/// its like map but for any type
19	fn xmap<O>(self, func: impl FnOnce(Self) -> O) -> O { func(self) }
20	/// its like inpsect but for any type
21	fn xtap(mut self, func: impl FnOnce(&mut Self)) -> Self {
22		func(&mut self);
23		self
24	}
25	fn xdebug(self) -> Self
26	where
27		Self: std::fmt::Debug,
28	{
29		println!("{:?}", self);
30		self
31	}
32	fn xdisplay(self) -> Self
33	where
34		Self: std::fmt::Display,
35	{
36		println!("{}", self);
37		self
38	}
39	fn xtap_mut(&mut self, func: impl FnOnce(&mut Self)) -> &mut Self {
40		func(self);
41		self
42	}
43	/// its like map but for our pipeline trait
44	fn xpipe<P: Pipeline<Self, O>, O>(self, pipeline: P) -> O {
45		pipeline.apply(self)
46	}
47
48	fn xref(&self) -> &Self { self }
49	fn xok<E>(self) -> Result<Self, E> { Ok(self) }
50	fn xsome(self) -> Option<Self> { Some(self) }
51
52	fn xinto<T: From<Self>>(self) -> T { T::from(self) }
53}
54impl<T: Sized> PipelineTarget for T {}
55
56
57/// Utilities for method-chaining on any type.
58/// Very similar in its goals to [`tap`](https://crates.io/crates/tap)
59pub trait PipelineTargetIter<T>: Sized + IntoIterator<Item = T> {
60	/// its [`IntoIterator::into_iter().map(func).collect()`]
61	fn xmap_each<O>(self, func: impl FnMut(T) -> O) -> Vec<O> {
62		self.into_iter().map(func).collect()
63	}
64	/// its [`IntoIterator::into_iter().filter_map(func).collect()`]
65	/// but flattens the results.
66	fn xtry_filter_map<O, E>(
67		self,
68		mut func: impl FnMut(T) -> Result<Option<O>, E>,
69	) -> Result<Vec<O>, E> {
70		let mut out = Vec::new();
71		for item in self.into_iter() {
72			match (func)(item) {
73				Ok(Some(o)) => out.push(o),
74				Ok(None) => {}
75				Err(e) => return Err(e),
76			}
77		}
78		Ok(out)
79	}
80}
81
82impl<T: Sized, I: IntoIterator<Item = T>> PipelineTargetIter<T> for I {}
83
84pub trait PipelineTargetVec<T> {
85	/// its [`Vec::extend`] but returns [`Self`]
86	fn xtend<I: IntoIterator<Item = T>>(self, iter: I) -> Self;
87}
88
89impl<T, T2> PipelineTargetVec<T> for T2
90where
91	T2: AsMut<Vec<T>>,
92{
93	fn xtend<I: IntoIterator<Item = T>>(mut self, iter: I) -> Self {
94		self.as_mut().extend(iter);
95		self
96	}
97}
98
99pub trait PipelineTargetString {
100	/// its [`String::push_str`] but returns [`Self`]
101	fn xtend(self, item: impl AsRef<str>) -> Self;
102}
103
104impl PipelineTargetString for String {
105	fn xtend(mut self, item: impl AsRef<str>) -> Self {
106		self.push_str(item.as_ref());
107		self
108	}
109}