1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! # Butcher
//!
//! An easy way to interact with `Cow`ed structs and enums.
//!
//! This crate provides the following functionalities for data wrapped in `Cow`:
//!   - [destructuring/pattern matching over structs and enums](#destructuringpattern-matching),
//!   - [iterating over collections, or any type that implements `IntoIterator`](#iteration),
//!   - [flattening `Cow`](#flattening),
//!   - [removing an indirection level `Cow`](#removing-an-indirection-level).
//!
//! ## Destructuring/pattern matching
//!
//! The `Butcher` trait can be used when it is necessary to destruture something
//! wrapped in a `Cow`. Below is a simple example:
//!
//! ```rust
//! use std::borrow::Cow;
//! use butcher::Butcher;
//!
//! #[derive(Butcher, Clone)]
//! struct MyNumberList {
//!     val: u32,
//!     next: Option<Box<MyNumberList>>,
//! }
//!
//! fn destructure_list_elem(i: Cow<MyNumberList>) -> (Cow<u32>, Cow<Option<Box<MyNumberList>>>) {
//!     let ButcheredMyNumberList { val, next } = Butcher::butcher(i);
//!
//!     (val, next)
//! }
//! ```
//!
//! This also allows pattern matching, as demonstrated in the following example:
//!
//! ```rust
//! 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 `Butcher` procedural macro can be derived for [structs][butcher-struct]
//! and for [enums][butcher-enum].
//!
//! [butcher-struct]: deriving_butcher_struct/index.html
//! [butcher-enum]: deriving_butcher_enum/index.html
//!
//! ## Iteration
//!
//! Here is a demonstration of how to iterate over an object wrapped in a `Cow`:
//!
//! ```rust
//! use std::borrow::Cow;
//! use butcher::iterator::{CowIter, IntoCowIterator};
//!
//! fn print_numbers(elems: Cow<[u32]>) {
//!     let mut iter = elems.into_cow_iter();
//!
//!     for element in iter {
//!         // The type of element is Cow<u32>
//!         println!("{:?}", element);
//!     }
//! }
//! ```
//!
//! See the documentation of [`CowIter`] for more information.
//!
//! [`CowIter`]: iterator/enum.CowIter.html
//!
//! ## Flattening
//!
//! In some situations, the `Butcher` proc macro can generate tricky fields,
//! such as nested `Cow`. The [`FlattenCow`] trait aims to remove such
//! flattening.
//!
//! [`FlattenCow`]: flatten/trait.FlattenCow.html
//!
//! ## Removing an indirection level
//!
//! The [`AsDerefCow`] trait allows to transform a given `Cow<T>` into a
//! `Cow<<T as Deref>::Target>`. This can be usefull when it is needed to
//! transform a `Cow<String>` into `Cow<str>`.
//!
//! [`AsDerefCow`]: as_deref/trait.AsDerefCow.html

pub mod as_deref;
pub mod deriving_butcher_enum;
pub mod deriving_butcher_struct;
pub mod flatten;
pub mod iterator;
pub mod methods;

pub use butcher_proc_macro::*;

use std::borrow::Cow;

pub trait Butcher<'cow>: ToOwned + 'cow {
    type Output: 'cow;

    fn butcher(this: Cow<'cow, Self>) -> Self::Output;

    fn unbutcher(this: Self::Output) -> Self;
}