lib.rs |
Create extensions for types you don't own with [extension traits] but without the boilerplate.
Example:
```rust
use extend::ext;
#[ext]
impl<T: Ord> Vec<T> {
fn sorted(mut self) -> Self {
self.sort();
self
}
}
assert_eq!(
vec![1, 2, 3],
vec![2, 3, 1].sorted(),
);
```
# How does it work?
Under the hood it generates a trait with methods in your `impl` and implements those for the
type you specify. The code shown above expands roughly to:
```rust
trait VecExt<T: Ord> {
fn sorted(self) -> Self;
}
impl<T: Ord> VecExt<T> for Vec<T> {
fn sorted(mut self) -> Self {
self.sort();
self
}
}
```
# Supported items
Extensions can contain methods or associated constants:
```rust
use extend::ext;
#[ext]
impl String {
const CONSTANT: &'static str = "FOO";
fn method() {
// ...
# todo!()
}
}
```
# Configuration
You can configure:
- The visibility of the trait. Use `pub impl ...` to generate `pub trait ...`. The default
visibility is private.
- The name of the generated extension trait. Example: `#[ext(name = MyExt)]`. By default we
generate a name based on what you extend.
- Which supertraits the generated extension trait should have. Default is no supertraits.
Example: `#[ext(supertraits = Default + Clone)]`.
More examples:
```rust
use extend::ext;
#[ext(name = SortedVecExt)]
impl<T: Ord> Vec<T> {
fn sorted(mut self) -> Self {
self.sort();
self
}
}
#[ext]
pub(crate) impl i32 {
fn double(self) -> i32 {
self * 2
}
}
#[ext(name = ResultSafeUnwrapExt)]
pub impl<T> Result<T, std::convert::Infallible> {
fn safe_unwrap(self) -> T {
match self {
Ok(t) => t,
Err(_) => unreachable!(),
}
}
}
#[ext(supertraits = Default + Clone)]
impl String {
fn my_length(self) -> usize {
self.len()
}
}
```
For backwards compatibility you can also declare the visibility as the first argument to `#[ext]`:
```
use extend::ext;
#[ext(pub)]
impl i32 {
fn double(self) -> i32 {
self * 2
}
}
```
# async-trait compatibility
Async extensions are supported via [async-trait](https://crates.io/crates/async-trait).
Be aware that you need to add `#[async_trait]` _below_ `#[ext]`. Otherwise the `ext` macro
cannot see the `#[async_trait]` attribute and pass it along in the generated code.
Example:
```
use extend::ext;
use async_trait::async_trait;
#[ext]
#[async_trait]
impl String {
async fn read_file() -> String {
// ...
# todo!()
}
}
```
# Other attributes
Other attributes provided _below_ `#[ext]` will be passed along to both the generated trait and
the implementation. See [async-trait compatibility](#async-trait-compatibility) above for an
example.
[extension traits]: https://dev.to/matsimitsu/extending-existing-functionality-in-rust-with-traits-in-rust-3622 |
19502 |