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
//! Cut down on trivial `impl From<A> for B` boilerplate code.
/// Implement conversion from `T` to its newtype wrapper.
///
/// Also works on types that convert to `T` via `into()`.
///
/// The wrapper can either be a newtype struct or a newtype variant of an enum:
/// - Struct
/// - Given `struct Foo(T);` and `impl From<U> for T`
/// - `newtype_wrap!(Foo, T);` implements `T -> Foo(T)`
/// - `newtype_wrap!(Foo, U);` implements `U -> Foo(T)`
/// - Enum
/// - Given `enum Foo{ Bar(T) };` and `impl From<U> for T`
/// - `newtype_wrap!(Foo, Bar, T);` implements `T -> Foo::Bar(T)`
/// - `newtype_wrap!(Foo, Bar, U);` implements `U -> Foo::Bar(T)`
#[macro_export]
macro_rules! newtype_wrap {
($wrapper: ident, $wrapped: ty) => {
impl From<$wrapped> for $wrapper {
fn from(val: $wrapped) -> Self {
$wrapper(val.into())
}
}
};
($wrapper: ty, $variant: ident, $wrapped: ty) => {
impl From<$wrapped> for $wrapper {
fn from(val: $wrapped) -> Self {
<$wrapper>::$variant(val.into())
}
}
};
}
/// The same as [`newtype_wrap`], except that the wrapping is implemented on
/// all types `U` that convert to `T` via `into()`.
///
/// Be careful when using this: there may be `U` types that you wish do not receive automatic wrapping.
/// In such a case, you should use [`newtype_wrap`] on each `U` type separately.
#[macro_export]
macro_rules! newtype_wrap_from_any {
($wrapper: ident, $wrapped: ty) => {
impl<T> From<T> for $wrapper
where
T: Into<$wrapped>,
{
fn from(val: T) -> Self {
$wrapper(val.into())
}
}
};
($wrapper: ty, $variant: ident, $wrapped: ty) => {
impl<T> From<T> for $wrapper
where
T: Into<$wrapped>,
{
fn from(val: T) -> Self {
<$wrapper>::$variant(val.into())
}
}
};
}
/// Implement conversion from `A` to `Z` via `B`, `C`, ...
///
/// `B` needs to implement `From<A>`, `C` needs to implement `From<B>`, and so on.
///
/// Example: `chained_into!(A, B, C, D, E);` implements `From<A> for E` by
/// converting `A` to `B`, then `B` to `C`, then `C` to `D`, and finally `D` to `E`.
#[macro_export]
macro_rules! chained_into {
($source: ty, $($tail: ty),+) => {
chained_into!(@impl $source | $($tail),+ | chained_into!(@get_target $($tail),+));
};
(@impl $source: ty | $($intermediate: ty),* | $target: ty) => {
impl From<$source> for $target {
fn from(val: $source) -> $target {
chained_into!(@next val, $($intermediate),*)
}
}
};
(@get_target $target: ty) => {
$target
};
(@get_target $_: ty, $($tail: ty),+) => {
chained_into!(@get_target $($tail),+)
};
(@next $val: expr, $intermediate: ty) => {
<$intermediate>::from($val)
};
(@next $val: expr, $intermediate: ty, $($tail: ty),+) => {
chained_into!(@next <$intermediate>::from($val), $($tail),+)
};
}