#[doc(hidden)]
#[macro_export]
macro_rules! option {
($ident:ident $(<$generic:ident>)?) => {
paste::paste! {
#[repr(transparent)]
pub(crate) struct [< Optional $ident >]$(<$generic>)?(
std::mem::ManuallyDrop<$ident$(<$generic>)?>
);
impl$(<$generic>)? [< Optional $ident >]$(<$generic>)? {
pub(crate) fn some<Value>(value: Value) -> Self
where
Value: Into<$ident$(<$generic>)?>
{
Self(std::mem::ManuallyDrop::new(value.into()))
}
pub(crate) fn none() -> Self {
Self(std::mem::ManuallyDrop::new($ident {
ptr: std::ptr::null_mut(),
len: 0,
cap: 0
}))
}
pub(crate) fn is_none(&self) -> bool {
self.0.ptr.is_null()
}
pub(crate) fn is_some(&self) -> bool {
!self.is_none()
}
pub(crate) fn into_option<Value>(mut self) -> Option<Value>
where
Value: From<$ident$(<$generic>)?>
{
if self.is_none() {
None
} else {
unsafe {
let inner = std::mem::ManuallyDrop::take(&mut self.0);
self.0.ptr = std::ptr::null_mut();
Some(inner.into())
}
}
}
}
impl<$($generic,)? Value> From<Option<Value>> for [< Optional $ident >]$(<$generic>)?
where
Value: Into<$ident$(<$generic>)?>
{
fn from(value: Option<Value>) -> Self {
value.map(Self::some).unwrap_or_else(Self::none)
}
}
impl<$($generic,)? Value> From<[< Optional $ident >]$(<$generic>)?> for Option<Value>
where
Value: From<$ident$(<$generic>)?>
{
fn from(value: [< Optional $ident >]$(<$generic>)?) -> Self {
value.into_option()
}
}
impl$(<$generic>)? Drop for [< Optional $ident >]$(<$generic>)? {
fn drop(&mut self) {
if self.is_some() {
unsafe {
std::mem::ManuallyDrop::drop(&mut self.0);
}
}
}
}
}
};
}