7 unstable releases (3 breaking)
0.5.1 | Aug 3, 2020 |
---|---|
0.5.0 | Aug 3, 2020 |
0.4.2 | Jul 24, 2020 |
0.3.0 | Jul 22, 2020 |
0.2.0 | Jul 19, 2020 |
#21 in #rust-patterns
Used in butcher
52KB
1.5K
SLoC
Butcher
An easy way to interact with structs and enums wrapped in Cow
.
Concept
The standard library has a clone on write type, which allows to work with data with either owned or borrowed data, without any distinction. However, this can lead to a lot of code duplication in some situations.
This crate currently provide the following functionalities:
- destucturing any struct wrapped in
Cow
, - pattern matching on structs and enum in
Cow
, - iteration over collections wrapped in
Cow
, Cow
flattening,Cow
unnesting.
Destructuring
The Butcher
trait can be derived on structs and enums. Destructuring is then
made easy:
use std::borrow::Cow;
use butcher::Butcher;
#[derive(Butcher, Clone)]
struct MyNumberList {
val: u32,
next: Option<Box<MyNumberList>>,
}
fn get_elem(i: Cow<MyNumberList>) -> Cow<u32> {
let ButcheredMyNumberList { val, .. } = Butcher::butcher(i);
val
}
Pattern matching
The Butcher
trait can also be derived on enums. This allows, for example:
use butcher::Butcher;
use std::borrow::Cow;
#[derive(Butcher, Clone)]
enum WebEvent {
PageLoad,
KeyPress(char),
Paste(String),
// or c-like structures.
Click { x: i64, y: i64 },
}
fn print_action(i: Cow<WebEvent>) {
match WebEvent::butcher(i) {
ButcheredWebEvent::PageLoad => { /* ... */ },
ButcheredWebEvent::KeyPress(key) => { /* ... */ },
ButcheredWebEvent::Paste(pasted) => { /* ... */ },
ButcheredWebEvent::Click { x, y } => { /* ... */ },
}
}
The fields in each variant will be Cow<T>
by default. This can be configured.
See the documentation for more information.
Iteration
This crate provide a CowIter
type, which allows to write Cow
fiendly
iterators. See this example:
use std::borrow::Cow;
use butcher::iterator::CowIter;
fn print_numbers(elems: Cow<[u32]>) {
let mut iter = CowIter::from(elems);
for element in iter {
// The type of element is Cow<u32>
println!("{:?}", element);
}
}
Flatening
Thanks to the Deref
trait, it is possible to flatten
a Cow<T>
to
Cow<<T as Deref>::Target>
. For instance, it is possible to create a Cow<str>
from a Cow<String>
, a Cow<[T]>
from a Cow<Vec<T>>
, and so on.
Thanks to how Deref
is defined, the target type is always infered by the
type inference system, which is very convenient.
use std::borrow::Cow;
use butcher::flatten::FlattenCow;
let some_cow: Cow<String> = Cow::Owned(String::from("Hello 🦀"));
let flattened_cow: Cow<str> = some_cow.flatten();
Unnesting
The Unnest
trait allows to simply remove nested usage of cow. It provides the
unnest
method, which transforms a Cow<Cow<T>>
into Cow<T>
.
use std::borrow::Cow;
use butcher::unnest::UnnestCow;
let foo: Cow<Cow<usize>> = Cow::Owned(Cow::Owned(42usize));
let foo_unnested: Cow<usize> = foo.unnest();
Minimum Supported Rust Version
This crate compiles in rust 1.42 and older. Upgrading MSRV is a breaking change. CI is set up so that it guarantees that the crate compiles and tests pass on both 1.42 and stable rust.
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Dependencies
~1.5MB
~37K SLoC