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}