#[macro_export]
macro_rules! free_lifetimes {
(
$(#[$attr:meta])*
$vis:vis struct $name:ident $($token:tt)*
) => {
$crate::generics_parse! {
$crate::free_lifetimes_impl {
@struct [$([$attr])*] [$vis] [$name]
}
$($token)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! free_lifetimes_impl {
(
@struct [$([$attr:meta])*] [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
{
$($(
$field:ident : $($field_lt:lifetime)? $field_mod:ident $field_ty:ty
),+ $(,)?)?
}
) => {
$crate::free_lifetimes_impl! {
@impl struct
[$name] [$([$attr])*] [$vis] [ty] [this] [builder]
[$($g)*] [$($r)*] [$($w)*]
[] [] [] [] []
[$($([$field : $($field_lt)? $field_mod $field_ty])+)?]
}
};
(
@struct [$([$attr:meta])*] [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
$($body:tt)*
) => {
$crate::std_compile_error!($crate::indoc_indoc!("
invalid free lifetimes struct definition, allowed form is
$(#[$attr:meta])*
$vis:vis struct $name:ident $(<$generics> $(where $where_clause)?)? {
$($(
$field:ident : $($lt:lifetime ref | $lt:lifetime mut | const) $ty:ty
),+ $(,)?)?
}
"));
};
(
@impl struct
[$name:ident] [$([$attr:meta])*] [$vis:vis] [$ty:ident] [$this:ident] [$builder:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($builder_lts:tt)*]
[$($builder_fields:tt)*]
[$($struct_fields:tt)*]
[$($ctor_assignments:tt)*]
[$($struct_methods:tt)*]
[[$field:ident : $field_lt:lifetime ref $field_ty:ty] $($other_fields:tt)*]
) => {
$crate::free_lifetimes_impl! {
@impl struct [$name] [$([$attr])*] [$vis] [$ty] [$this] [$builder] [$($g)*] [$($r)*] [$($w)*]
[
$($builder_lts)*
[$field_lt]
]
[
$($builder_fields)*
pub $field : & $field_lt $field_ty,
]
[
$($struct_fields)*
$field : &'static $field_ty,
]
[
$($ctor_assignments)*
$field : unsafe { &*($builder . $field as *const $field_ty) },
]
[
$($struct_methods)*
$vis fn $field (&self) -> &$field_ty { self.$field }
]
[$($other_fields)*]
}
};
(
@impl struct
[$name:ident] [$([$attr:meta])*] [$vis:vis] [$ty:ident] [$this:ident] [$builder:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($builder_lts:tt)*]
[$($builder_fields:tt)*]
[$($struct_fields:tt)*]
[$($ctor_assignments:tt)*]
[$($struct_methods:tt)*]
[[$field:ident : $field_lt:lifetime mut $field_ty:ty] $($other_fields:tt)*]
) => {
$crate::free_lifetimes_impl! {
@impl struct [$name] [$([$attr])*] [$vis] [$ty] [$this] [$builder] [$($g)*] [$($r)*] [$($w)*]
[
$($builder_lts)*
[$field_lt]
]
[
$($builder_fields)*
pub $field : & $field_lt mut $field_ty,
]
[
$($struct_fields)*
$field : &'static mut $field_ty,
]
[
$($ctor_assignments)*
$field : unsafe { &mut *($builder . $field as *mut $field_ty) },
]
[
$($struct_methods)*
#[allow(dead_code)]
$vis fn $field (&self) -> &$field_ty { self.$field }
#[allow(dead_code)]
$vis fn [< $field _mut >] (&mut self) -> &mut $field_ty { self.$field }
]
[$($other_fields)*]
}
};
(
@impl struct
[$name:ident] [$([$attr:meta])*] [$vis:vis] [$ty:ident] [$this:ident] [$builder:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($builder_lts:tt)*]
[$($builder_fields:tt)*]
[$($struct_fields:tt)*]
[$($ctor_assignments:tt)*]
[$($struct_methods:tt)*]
[[$field:ident : const $field_ty:ty] $($other_fields:tt)*]
) => {
$crate::free_lifetimes_impl! {
@impl struct [$name] [$([$attr])*] [$vis] [$ty] [$this] [$builder] [$($g)*] [$($r)*] [$($w)*]
[$($builder_lts)*]
[
$($builder_fields)*
pub $field : $field_ty,
]
[
$($struct_fields)*
$field : $field_ty,
]
[
$($ctor_assignments)*
$field: $builder . $field,
]
[
$($struct_methods)*
$vis fn $field (&self) -> $field_ty { self.$field }
]
[$($other_fields)*]
}
};
(
@impl struct
[$name:ident] [$([$attr:meta])*] [$vis:vis] [$ty:ident] [$this:ident] [$builder:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($builder_lts:tt)*]
[$($builder_fields:tt)*]
[$($struct_fields:tt)*]
[$($ctor_assignments:tt)*]
[$($struct_methods:tt)*]
[[$field:ident : $($field_lt:lifetime)? $field_mod:ident $field_ty:ty] $($other_fields:tt)*]
) => {
$crate::std_compile_error!($crate::std_concat!(
"invalid free lifetimes struct field '",
$crate::std_stringify!($field : $($field_lt)? $field_mod $field_ty),
"\
', allowed form is '\
$field:ident : $($lt:lifetime ref | $lt:lifetime mut | const) $ty:ty\
'\
",
));
};
(
@impl struct
[$name:ident] [$([$attr:meta])*] [$vis:vis] [$ty:ident] [$this:ident] [$builder:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($([$builder_lts:tt])+)?]
[$($builder_fields:tt)*]
[$($struct_fields:tt)*]
[$($ctor_assignments:tt)*]
[$($struct_methods:tt)*]
[]
) => {
$crate::generics_concat! {
$crate::free_lifetimes_impl {
@impl [$name] [$([$attr])*] [$vis] [$ty] [$this] [$builder] [$($g)*] [$($r)*] [$($w)*]
[$($builder_fields)*]
[$($struct_fields)*]
[$($ctor_assignments)*]
[$($struct_methods)*]
}
[$( < $($builder_lts),+ > )?] [$( < $($builder_lts),+ > )?] [],
[$($g)*] [$($r)*] [$($w)*]
}
};
(
@impl
[$name:ident] [$([$attr:meta])*] [$vis:vis] [$ty:ident] [$this:ident] [$builder:ident]
[$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
[$($builder_fields:tt)*]
[$($struct_fields:tt)*]
[$($ctor_assignments:tt)*]
[$($struct_methods:tt)*]
[$($builder_g:tt)*] [$($builder_r:tt)*] [$($builder_w:tt)*]
) => {
$crate::paste_paste! {
$vis struct [< $name Builder >] $($builder_g)* $($w)* {
$($builder_fields)*
}
impl $($builder_g)* [< $name Builder >] $($builder_r)* $($builder_w)* {
$vis fn build_and_then<FreeLifetimesStructBuildReturnType>(
&mut self,
f: impl $crate::std_ops_FnOnce(&mut $name $($r)*) -> FreeLifetimesStructBuildReturnType
) -> FreeLifetimesStructBuildReturnType {
let $builder = self;
let mut free_lifetimes = $name {
$($ctor_assignments)*
};
f(&mut free_lifetimes)
}
}
$(#[$attr])*
$vis struct $name $($g)* $($w)* {
$($struct_fields)*
}
impl $($g)* $name $($r)* $($w)* {
$($struct_methods)*
}
}
};
}
#[cfg(docsrs)]
pub mod free_lifetimes_example {
pub struct Data {
pub x: i16,
pub y: i16
}
free_lifetimes! {
pub struct FreeLifetimesStruct {
data: 'data mut Data,
str_data: 'str_data ref str,
id: const usize,
}
}
}