powerletters/lib.rs
1//! # Power Letters for Rust
2//!
3//! Concise spellings of common Rust operations:
4//!
5//! - `C` - `Clone`
6//! - `O` - `ToOwned`
7//! - `S` - `ToString`
8//! - `I` - Ignore `Result`
9//! - `X` - `expect` for `Result` and `Option`
10//!
11//! All operations are provided as both functions and methods.
12//! Sometimes one reads better than the other.
13//!
14//!
15//! ### Power `Clone`
16//!
17//! ```
18//! use powerletters::*;
19//!
20//! let bagostuff = vec!["a", "b", "c"];
21//! let newbag = bagostuff.C();
22//!
23//! // or
24//! let newbag = C(&bagostuff);
25//! ```
26//!
27//!
28//! ### Power `ToOwned`
29//!
30//! ```
31//! use powerletters::*;
32//! use std::path::Path;
33//!
34//! let yourpath = Path::new("chill");
35//! let mypath = yourpath.O();
36//!
37//! // or
38//! let mypath = O(yourpath);
39//! ```
40//!
41//!
42//! ### Power `ToString`
43//!
44//! ```
45//! use powerletters::*;
46//!
47//! let s: String = S("foo");
48//!
49//! // or
50//! let s: String = "foo".S();
51//! ```
52//!
53//!
54//! ### Power ignore `Result` - kick that `Result` to the curb!
55//!
56//! ```
57//! use powerletters::*;
58//! use std::io::Write;
59//!
60//! let mut buf = Vec::new();
61//! write!(&mut buf, "hello").I();
62//!
63//! // or
64//! I(write!(&mut buf, "world"));
65//! ```
66//!
67//! Note this is superior to `let _ = ...`
68//! because the `let` version is untyped and can
69//! introduce unintended bugs like ignoring futures.
70//!
71//!
72//! ### Power `expect` for `Result` and `Option`.
73//!
74//! ```
75//! use powerletters::*;
76//! # use std::io;
77//!
78//! let maybe_thing = Some("thing");
79//! let thing = maybe_thing.X(); // like `.expect("some baloney")`
80//! let good_thing: Result<_, io::Error> = Ok("thing");
81//! let thing = good_thing.X();
82//!
83//! // or
84//! let maybe_thing = Some("thing");
85//! let thing = X(maybe_thing);
86//! let good_thing: Result<_, io::Error> = Ok("thing");
87//! let thing = X(good_thing);
88//! ```
89
90/// Power [`Clone`].
91#[allow(non_snake_case)]
92pub fn C<T>(o: &T) -> T
93where
94 T: Clone,
95{
96 o.clone()
97}
98
99/// Power [`ToOwned`].
100#[allow(non_snake_case)]
101pub fn O<T>(o: &T) -> T::Owned
102where
103 T: ToOwned + ?Sized,
104{
105 ToOwned::to_owned(o)
106}
107
108/// Power [`ToString`].
109#[allow(non_snake_case)]
110pub fn S<T>(s: &T) -> String
111where
112 T: ToString + ?Sized,
113{
114 ToString::to_string(s)
115}
116
117/// Power ignore [`Result`] - kick that `Result` to the curb!
118#[allow(non_snake_case)]
119pub fn I<T, E>(r: Result<T, E>) {
120 let _ = r;
121}
122
123/// Power `expect` for [`Result`] and [`Option`].
124#[track_caller]
125#[allow(non_snake_case)]
126pub fn X<T>(v: T) -> T::Output
127where
128 T: PowerExpect,
129{
130 v.X()
131}
132
133// //
134// -------------- //
135// //
136
137// ^ those are barbells, for power
138
139
140/// Power [`Clone`].
141pub trait PowerClone {
142 #[allow(non_snake_case)]
143 fn C(&self) -> Self;
144}
145
146impl<T> PowerClone for T
147where
148 T: Clone,
149{
150 #[allow(non_snake_case)]
151 fn C(&self) -> T {
152 self.clone()
153 }
154}
155
156/// Power [`ToOwned`].
157pub trait PowerToOwned {
158 type Owned;
159 #[allow(non_snake_case)]
160 fn O(&self) -> Self::Owned;
161}
162
163impl<T> PowerToOwned for T
164where
165 T: ToOwned + ?Sized,
166{
167 type Owned = T::Owned;
168
169 #[allow(non_snake_case)]
170 fn O(&self) -> Self::Owned {
171 ToOwned::to_owned(self)
172 }
173}
174
175/// Power [`ToString`].
176pub trait PowerToString {
177 #[allow(non_snake_case)]
178 fn S(&self) -> String;
179}
180
181impl<T> PowerToString for T
182where
183 T: ToString + ?Sized,
184{
185 #[allow(non_snake_case)]
186 fn S(&self) -> String {
187 ToString::to_string(self)
188 }
189}
190
191/// Power ignore [`Result`] - kick that `Result` to the curb!
192pub trait ResultIgnore {
193 #[allow(non_snake_case)]
194 fn I(self);
195}
196
197impl<T, E> ResultIgnore for Result<T, E> {
198 #[track_caller]
199 #[allow(non_snake_case)]
200 fn I(self) {
201 let _ = self;
202 }
203}
204
205/// Power `expect` for [`Result`] and [`Option`].
206pub trait PowerExpect {
207 type Output;
208 #[allow(non_snake_case)]
209 fn X(self) -> Self::Output;
210}
211
212impl<T> PowerExpect for Option<T> {
213 type Output = T;
214
215 #[track_caller]
216 fn X(self) -> T {
217 match self {
218 Some(v) => v,
219 None => panic!("impossible `None` option"),
220 }
221 }
222}
223
224impl<T, E: std::fmt::Display> PowerExpect for Result<T, E> {
225 type Output = T;
226
227 #[track_caller]
228 fn X(self) -> T {
229 match self {
230 Ok(v) => v,
231 Err(e) => panic!("impossible `Err` result: {e}"),
232 }
233 }
234}