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::*;