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
//! `projection` provides you easy access struct fields of a Option<T>.
//!
//! # Examples
//!
//! To use `projection`, you first need to annotate your type with the `projection` attribute
//!
//! ```
//! use ::projection::projection;
//! #[projection]
//! struct AType {
//!     a: u32,
//!     b: u32
//! }
//! ```
//!
//! Then, you can use `project()` to access fields of `AType` from a `Option<AType>`
//!
//! ```
//! # use ::projection::projection;
//! # #[projection]
//! # struct AType {
//! #     a: u32,
//! #     b: u32
//! # }
//! use ::projection::prelude::*;
//!
//! let var: Option<AType> = None;
//! let var = var.project();
//! assert_eq!(var.a, None);
//!
//! let var = Some(AType { a: 1, b: 1 });
//! let var = var.project();
//! assert_eq!(var.a, Some(1));
//!
//! // You can choose to borrow the values
//! let mut var = Some(AType { a: 1, b: 1 });
//! let var = var.as_mut().project();
//! assert_eq!(var.a, Some(&mut 1));
//!
//! let var = Some(AType { a: 1, b: 1 });
//! let var = var.as_ref().project();
//! assert_eq!(var.a, Some(&1));
//! ```

pub use projection_macros::projection;

pub mod prelude {
	/// Implemented for `T` where a projection can be created for `Option<T>`
	pub trait OptionProjectable: Sized {
		type P;
		fn project(f: Option<Self>) -> Self::P;
	}
	#[doc(hidden)]
	pub trait ResultProjectable<E>: Sized {
		type P;
		fn project(f: Result<Self, E>) -> Self::P;
	}

	/// Provides `.project()` for `Option<T>`
	pub trait Projectable {
		type P;
		fn project(self) -> Self::P;
	}

	impl<T: OptionProjectable> Projectable for Option<T> {
		type P = <T as OptionProjectable>::P;
		fn project(self) -> <T as OptionProjectable>::P {
			OptionProjectable::project(self)
		}
	}

	impl<E, T: ResultProjectable<E>> Projectable for Result<T, E> {
		type P = <T as ResultProjectable<E>>::P;
		fn project(self) -> <T as ResultProjectable<E>>::P {
			ResultProjectable::project(self)
		}
	}
}

pub use crate::prelude::*;