somok/lib.rs
1#![deny(missing_docs)]
2//! # Somok - postfix Result/Option wrapping
3//!
4//! ## Usage:
5//! Add following to your cargo toml:
6//! ```toml
7//! somok = "1.0"
8//! ```
9//! Then use postfix wrapping as follows:
10//! ```rust
11//! use somok::Somok;
12//!
13//! fn foo() -> Result<Option<String>> {
14//! String::from("Foobar").some().okay()
15//! }
16//! ```
17
18/// Postfix wrapping in Result and Option
19/// ### Usage:
20/// ```rust
21/// fn foo() -> Result<Option<String>> {
22/// String::from("Foobar").some().okay()
23/// }
24/// ```
25pub trait Somok: Sized {
26 /// Returns self wrapped in Ok
27 fn okay<E>(self) -> Result<Self, E> {
28 Ok(self)
29 }
30 /// Returns self wrapped in Err
31 fn error<T>(self) -> Result<T, Self> {
32 Err(self)
33 }
34 /// Returns self wrapped in Some
35 fn some(self) -> Option<Self> {
36 Some(self)
37 }
38 /// Returns boxed self
39 fn boxed(self) -> Box<Self> {
40 Box::new(self)
41 }
42 /// Returns self wrapped in `Either::Left`
43 fn left<R>(self) -> Either<Self, R> {
44 Either::Left(self)
45 }
46 /// Returns self wrapped in `Either::Right`
47 fn right<L>(self) -> Either<L, Self> {
48 Either::Right(self)
49 }
50}
51impl<T: Sized> Somok for T {}
52
53/// Postfix notation for leaking the box
54pub trait Leaksome<T: ?Sized> {
55 /// Leaks the box
56 fn leak(self) -> &'static mut T;
57}
58impl<T: ?Sized> Leaksome<T> for Box<T> {
59 fn leak(self) -> &'static mut T {
60 Box::leak(self)
61 }
62}
63
64/// Fallible `remove()` alternative for Vec
65pub trait TryRemove {
66 /// Type of collection item
67 type Item;
68 /// Attempts to `remove` item at index
69 fn try_remove(&mut self, i: usize) -> Option<Self::Item>;
70}
71impl<T> TryRemove for Vec<T> {
72 type Item = T;
73
74 fn try_remove(&mut self, i: usize) -> Option<Self::Item> {
75 if i < self.len() {
76 self.remove(i).some()
77 } else {
78 None
79 }
80 }
81}
82
83/// Convinience method for conditionally popping from a collection
84pub trait CondPop {
85 /// Type of collection item
86 type Item;
87 /// Conditionally pops off an item from collection
88 fn cond_pop<F>(&mut self, cond: F) -> Option<Self::Item>
89 where
90 F: Fn(&Self::Item) -> bool;
91}
92impl<T> CondPop for Vec<T> {
93 type Item = T;
94
95 fn cond_pop<F>(&mut self, cond: F) -> Option<Self::Item>
96 where
97 F: Fn(&Self::Item) -> bool,
98 {
99 if let Some(last) = self.last() {
100 cond(last).then(|| self.pop()).flatten()
101 } else {
102 None
103 }
104 }
105}
106
107/// Enum representing either of two options
108#[derive(Debug, Clone, Copy)]
109pub enum Either<L, R> {
110 /// Left variant
111 Left(L),
112 /// Right variant
113 Right(R),
114}
115
116/// Enum representing partitioning choice in `PartitionThree`
117pub enum Ternary {
118 /// Variant representing first partition option
119 First,
120 /// Variant representing second partition option
121 Second,
122 /// Variant representing third partition option
123 Third,
124}
125
126/// Trait providing method analogous to `Iterator::partition`
127/// but resulting in three distinct groupings
128pub trait PartitionThree: Iterator {
129 /// Consumes an iterator, creating three collections from it.
130 /// The predicate passed to partition() can return `First`, `Second`, or `Third`. partition() returns a triple,
131 /// all of the elements for which it returned `First`, all of the elements for which it returned `Second`, and all of the elements for which it returned `Third`.
132 fn partition_three<C, F>(self, f: F) -> (C, C, C)
133 where
134 Self: Sized,
135 C: Default + Extend<<Self as Iterator>::Item>,
136 F: FnMut(&<Self as Iterator>::Item) -> Ternary,
137 {
138 #[inline]
139 fn extend<'a, T, C: Extend<T>>(
140 mut f: impl FnMut(&T) -> Ternary + 'a,
141 first: &'a mut C,
142 second: &'a mut C,
143 third: &'a mut C,
144 ) -> impl FnMut((), T) + 'a {
145 move |(), x| match f(&x) {
146 Ternary::First => first.extend([x]),
147 Ternary::Second => second.extend([x]),
148 Ternary::Third => third.extend([x]),
149 }
150 }
151
152 let mut first = C::default();
153 let mut second = C::default();
154 let mut third = C::default();
155
156 self.fold((), extend(f, &mut first, &mut second, &mut third));
157 (first, second, third)
158 }
159}
160
161impl<T: Iterator> PartitionThree for T {}