powerset_enum/
lib.rs

1//! The [`#[powerset_enum]`](../powerset_enum_attr/attr.powerset_enum.html) attribute parametrizes an `enum` to make it a powerset (set of all
2//! subsets), and create a macro with the same name of the `enum` for easy notation of the subsets.
3//!
4//! Note: this is a nightly only crate, and to use it you need to enable the following feature
5//! flags:
6//!
7//! ```ignore
8//! #![feature(never_type, exhaustive_patterns, proc_macro_hygiene)]
9//! ```
10//!
11//! Each variant of the `enum` decorated by `#[powerset_enum]` must be a tuple-struct variant with
12//! a single item, and the type of that item must be unique within that `enum`.  Parametrization of
13//! the `enum` (beside the one created by `#[powerset_enum]`) is not supported.
14//!
15//! To use a specific parametrization, use a macro with the same name of the enum and provide to it
16//! the list of types you require.
17//!
18//! An `upcast` method is created on the `enum` type to convert any subset to any superset of that
19//! subsets. Usually used with [Result::map_err].
20//!
21//! ```ignore
22//! fn foo(...) -> Result<..., E![A, B]> {
23//!     ...
24//! }
25//! fn bar(...) -> Result<..., E![A, B, C, D]> {
26//!     foo(...).map_err(E::upcast)
27//! }
28//! ```
29//!
30//! The [Extract] `trait` provides an `extract` method on the `enum` type and on [Result] with the
31//! `enum` as their error to extract a new [Result] where the OK value is the original value
32//! without the extracted variant and the error is the extracted variant:
33//!
34//! ```ignore
35//! fn baz(...) -> Result<..., E![A, B, D]> {
36//!     bar(...).extract::<C>().expect("C is not allowed at all")
37//! }
38//! ```
39//!
40//! ```
41//! #![feature(never_type, exhaustive_patterns, proc_macro_hygiene)]
42//! # use powerset_enum::*;
43//!
44//! # #[derive(Debug, PartialEq)]
45//! pub struct Exception1;
46//! # #[derive(Debug, PartialEq)]
47//! pub struct Exception2;
48//! # #[derive(Debug, PartialEq)]
49//! pub struct Exception3;
50//!
51//! #[powerset_enum]
52//! # #[derive(Debug, PartialEq)]
53//! pub enum Error {
54//!     Exception1(Exception1),
55//!     Exception2(Exception2),
56//!     Exception3(Exception3),
57//! }
58//!
59//! fn foo(x: usize) -> Result<usize, Error![Exception1, Exception2]> {
60//!     Ok(match x {
61//!         1 => Err(Exception1)?,
62//!         2 => Err(Exception2)?,
63//!         x => x,
64//!     })
65//! }
66//!
67//! fn bar(x: usize) -> Result<usize, Error![Exception1, Exception3]> {
68//!     if x == 3 {
69//!         Err(Exception3)?;
70//!     }
71//!     foo(x)
72//!         // Specifically handle `Exception2`:
73//!         .extract::<Exception2>().unwrap_or(Ok(2))
74//!         // Convert `Result<usize, Error![Exception1]>` to `Result<usize, Error![Exception1, Exception3]>`:
75//!         .map_err(Error::upcast)
76//! }
77//!
78//! fn main() {
79//!     let x = 1;
80//!
81//!     match foo(x) {
82//!         Ok(n) => println!("OK - got {}", n),
83//!         Err(Error::Exception1(_)) => println!("Got exception 1"),
84//!         Err(Error::Exception2(_)) => println!("Got exception 2"),
85//!         // No Exception3 match arm needed - `foo` cannot return it
86//!     }
87//!
88//!     match bar(x) {
89//!         Ok(n) => println!("OK - got {}", n),
90//!         Err(Error::Exception1(_)) => println!("Got exception 1"),
91//!         // No Exception2 match arm needed - `bar` cannot return it
92//!         Err(Error::Exception3(_)) => println!("Got exception 3"),
93//!     }
94//! }
95//! ```
96
97pub use powerset_enum_attr::{powerset_enum, powerset};
98pub use powerset_enum_traits::*;