#[doc(hidden)]
#[macro_export]
macro_rules! _private_modules_unit {
($_t:tt) => {
()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! _private_define_modules {
(
$(#[$($enum_attr:tt)*])*
$vis:vis enum $name:ident {
$(
$(#[$($vattr:tt)*])*
$variant:ident
),* $(,)?
}
$($trailing:tt)*
) => {
$crate::_private_define_modules! {
@walk_enum_attrs
attrs: { $( #[$($enum_attr)*] )* }
pass: { }
os: { }
tail: {
vis: [$vis]
name: [$name]
trailing: [$($trailing)*]
variants: [ $( { [$(#[$($vattr)*])*] $variant } )* ]
}
}
};
(
@walk_enum_attrs
attrs: { #[os($($args:tt)*)] $($more:tt)* }
pass: $pass:tt
os: { }
tail: $tail:tt
) => {
$crate::_private_define_modules! {
@walk_enum_attrs
attrs: { $($more)* }
pass: $pass
os: { $($args)* }
tail: $tail
}
};
(
@walk_enum_attrs
attrs: { #[os($($args:tt)*)] $($more:tt)* }
pass: $pass:tt
os: { $($_old:tt)+ }
tail: $tail:tt
) => {
compile_error!("`#[os(...)]` may only appear once on the enum");
};
(
@walk_enum_attrs
attrs: { #[$($other:tt)*] $($more:tt)* }
pass: { $($pass:tt)* }
os: $os:tt
tail: $tail:tt
) => {
$crate::_private_define_modules! {
@walk_enum_attrs
attrs: { $($more)* }
pass: { $($pass)* #[$($other)*] }
os: $os
tail: $tail
}
};
(
@walk_enum_attrs
attrs: { }
pass: { $($pass:tt)* }
os: $os:tt
tail: {
vis: [$vis:vis]
name: [$name:ident]
trailing: [$($trailing:tt)*]
variants: [ $({ [$($vattr:tt)*] $variant:ident })* ]
}
) => {
$crate::_private_define_modules! {
@process_variants
ctx { [$($pass)*] [$vis] [$name] [$($trailing)*] [$os] }
input { $( { [$($vattr)*] $variant } )* }
output { }
}
};
(
@process_variants
ctx $ctx:tt
input { }
output $output:tt
) => {
$crate::_private_define_modules! {
@finalize
ctx $ctx
output $output
}
};
(
@process_variants
ctx $ctx:tt
input { { [ $($attrs:tt)* ] $variant:ident } $($rest:tt)* }
output $output:tt
) => {
$crate::_private_split_reactor_attrs! {
peel: module
state: {
ctx $ctx
input { $($rest)* }
output $output
variant { $variant }
}
pass: { }
found: { }
attrs: { $($attrs)* }
}
};
(
@after_split
state: {
ctx $ctx:tt
input $input:tt
output $output:tt
variant { $variant:ident }
}
pass: $pass:tt
found: { }
) => {
compile_error!(concat!(
"module variant `", stringify!($variant), "` is missing `#[module(name = \"...\")]`"
));
};
(
@after_split
state: {
ctx $ctx:tt
input $input:tt
output $output:tt
variant $variant:tt
}
pass: $pass:tt
found: { $($margs:tt)* }
) => {
$crate::_private_define_modules! {
@parse_module_args
ctx $ctx
input $input
output $output
variant $variant
pass $pass
name { }
mode { kernel }
optional { false }
args { $($margs)* }
}
};
(
@parse_module_args
ctx $ctx:tt
input $input:tt
output $output:tt
variant $variant:tt
pass $pass:tt
name $_old_name:tt
mode $mode:tt
optional $opt:tt
args { name = $name:literal $(, $($rest:tt)*)? }
) => {
$crate::_private_define_modules! {
@parse_module_args
ctx $ctx
input $input
output $output
variant $variant
pass $pass
name { $name }
mode $mode
optional $opt
args { $($($rest)*)? }
}
};
(
@parse_module_args
ctx $ctx:tt
input $input:tt
output $output:tt
variant $variant:tt
pass $pass:tt
name $name:tt
mode $_old_mode:tt
optional $opt:tt
args { mode($($mode_args:tt)*) $(, $($rest:tt)*)? }
) => {
$crate::_private_define_modules! {
@parse_module_args
ctx $ctx
input $input
output $output
variant $variant
pass $pass
name $name
mode { $($mode_args)* }
optional $opt
args { $($($rest)*)? }
}
};
(
@parse_module_args
ctx $ctx:tt
input $input:tt
output $output:tt
variant $variant:tt
pass $pass:tt
name $name:tt
mode $mode:tt
optional $_old_opt:tt
args { optional $(, $($rest:tt)*)? }
) => {
$crate::_private_define_modules! {
@parse_module_args
ctx $ctx
input $input
output $output
variant $variant
pass $pass
name $name
mode $mode
optional { true }
args { $($($rest)*)? }
}
};
(
@parse_module_args
ctx $ctx:tt
input $input:tt
output $output:tt
variant { $variant:ident }
pass $pass:tt
name { }
mode $mode:tt
optional $opt:tt
args { }
) => {
compile_error!(concat!(
"module variant `", stringify!($variant), "` is missing `name = \"...\"` in `#[module(...)]`"
));
};
(
@parse_module_args
ctx $ctx:tt
input $input:tt
output { $($out:tt)* }
variant { $variant:ident }
pass { $($pass:tt)* }
name { $mod_name:literal }
mode { $($mode_args:tt)* }
optional { $opt:tt }
args { }
) => {
$crate::_private_define_modules! {
@process_variants
ctx $ctx
input $input
output {
$($out)*
{
variant: $variant,
pass: [$($pass)*],
name: $mod_name,
mode: { $($mode_args)* },
optional: $opt,
}
}
}
};
(
@finalize
ctx {
[$($eattr:tt)*]
[$vis:vis]
[$name:ident]
[
#[resolver] $rvis:vis struct $resolver:ident;
#[cache] $cvis:vis struct $cache:ident;
]
[$os:tt]
}
output $variants:tt
) => {
$crate::_private_define_modules! {
@emit
attrs: [$($eattr)*] vis: [$vis] name: [$name] os: $os
variants: $variants
resolver: { yes $rvis $resolver }
cache: { yes $cvis $cache }
}
};
(
@finalize
ctx {
[$($eattr:tt)*]
[$vis:vis]
[$name:ident]
[
#[cache] $cvis:vis struct $cache:ident;
#[resolver] $rvis:vis struct $resolver:ident;
]
[$os:tt]
}
output $variants:tt
) => {
$crate::_private_define_modules! {
@emit
attrs: [$($eattr)*] vis: [$vis] name: [$name] os: $os
variants: $variants
resolver: { yes $rvis $resolver }
cache: { yes $cvis $cache }
}
};
(
@finalize
ctx {
[$($eattr:tt)*]
[$vis:vis]
[$name:ident]
[
#[resolver] $rvis:vis struct $resolver:ident;
]
[$os:tt]
}
output $variants:tt
) => {
$crate::_private_define_modules! {
@emit
attrs: [$($eattr)*] vis: [$vis] name: [$name] os: $os
variants: $variants
resolver: { yes $rvis $resolver }
cache: { no }
}
};
(
@finalize
ctx {
[$($eattr:tt)*]
[$vis:vis]
[$name:ident]
[
#[cache] $cvis:vis struct $cache:ident;
]
[$os:tt]
}
output $variants:tt
) => {
compile_error!("`#[cache]` requires `#[resolver]`");
};
(
@finalize
ctx {
[$($eattr:tt)*]
[$vis:vis]
[$name:ident]
[ ]
[$os:tt]
}
output $variants:tt
) => {
$crate::_private_define_modules! {
@emit
attrs: [$($eattr)*] vis: [$vis] name: [$name] os: $os
variants: $variants
resolver: { no }
cache: { no }
}
};
(
@emit
attrs: [$($eattr:tt)*]
vis: [$vis:vis]
name: [$name:ident]
os: $os:tt
variants: {
$(
{
variant: $variant:ident,
pass: [$($pass:tt)*],
name: $mod_name:literal,
mode: { $($mode_args:tt)* },
optional: $opt:tt,
}
)*
}
resolver: $resolver:tt
cache: $cache:tt
) => {
$($eattr)*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
$vis enum $name {
$(
$($pass)*
$variant,
)*
}
$crate::_private_define_modules! {
@emit_impl
name: [$name]
os: $os
variants: {
$(
{
variant: $variant,
name: $mod_name,
mode: { $($mode_args)* },
optional: $opt,
}
)*
}
}
$crate::_private_define_modules! {
@emit_resolver
name: [$name]
variants: { $( { variant: $variant, name: $mod_name, optional: $opt } )* }
resolver: $resolver
cache: $cache
}
};
(
@emit_impl
name: [$name:ident]
os: { }
variants: {
$(
{
variant: $variant:ident,
name: $mod_name:literal,
mode: { $($mode_args:tt)* },
optional: $opt:tt,
}
)*
}
) => {
impl<__Os> $crate::reactor::ReactorModule<__Os> for $name
where
__Os: $crate::reactor::macros::__private::vmi_core::VmiOs + 'static,
{
const METADATA: &'static [$crate::reactor::ModuleMetadata<Self, __Os>] = &[
$crate::reactor::ModuleMetadata {
name: "kernel",
module: ::std::option::Option::None,
mode: $crate::reactor::ModuleMode::Kernel,
optional: true,
},
$(
$crate::reactor::ModuleMetadata {
name: $mod_name,
module: ::std::option::Option::Some(Self::$variant),
mode: $crate::_private_define_modules!(
@mode_expr { $($mode_args)* } turbofish: { ::<__Os> }
),
optional: $opt,
},
)*
];
const KERNEL_SLOT: usize = 0;
fn slot(self) -> usize {
self as usize + 1
}
}
};
(
@emit_impl
name: [$name:ident]
os: {
< $( $g_param:ident $( : $g_bound:ident )? ),+ >
$os_ty:ty
$( where $($bounds:tt)* )?
}
variants: $variants:tt
) => {
$crate::_private_define_modules! {
@emit_impl_anchored
name: [$name]
impl_generics: [ $( $g_param $( : $g_bound )? ),+ ]
os_ty: [$os_ty]
where_bounds: [ $( $($bounds)* )? ]
variants: $variants
}
};
(
@emit_impl
name: [$name:ident]
os: {
$os_ty:ty
$( where $($bounds:tt)* )?
}
variants: $variants:tt
) => {
$crate::_private_define_modules! {
@emit_impl_anchored
name: [$name]
impl_generics: [ ]
os_ty: [$os_ty]
where_bounds: [ $( $($bounds)* )? ]
variants: $variants
}
};
(
@emit_impl_anchored
name: [$name:ident]
impl_generics: [ $($impl_generics:tt)* ]
os_ty: [$os_ty:ty]
where_bounds: [ $($bounds:tt)* ]
variants: {
$(
{
variant: $variant:ident,
name: $mod_name:literal,
mode: { $($mode_args:tt)* },
optional: $opt:tt,
}
)*
}
) => {
impl<$($impl_generics)*> $crate::reactor::ReactorModule<$os_ty> for $name
where
$($bounds)*
{
const METADATA: &'static [$crate::reactor::ModuleMetadata<Self, $os_ty>] = &[
$crate::reactor::ModuleMetadata {
name: "kernel",
module: ::std::option::Option::None,
mode: $crate::reactor::ModuleMode::Kernel,
optional: true,
},
$(
$crate::reactor::ModuleMetadata {
name: $mod_name,
module: ::std::option::Option::Some(Self::$variant),
mode: $crate::_private_define_modules!(
@mode_expr { $($mode_args)* } turbofish: { }
),
optional: $opt,
},
)*
];
const KERNEL_SLOT: usize = 0;
fn slot(self) -> usize {
self as usize + 1
}
}
};
(@mode_expr { kernel } turbofish: $tf:tt) => {
$crate::reactor::ModuleMode::Kernel
};
(@mode_expr { user } turbofish: $tf:tt) => {
$crate::reactor::ModuleMode::User {
process: ::std::option::Option::None,
}
};
(@mode_expr { user, process = $name:literal } turbofish: $tf:tt) => {
$crate::reactor::ModuleMode::User {
process: ::std::option::Option::Some(
$crate::reactor::ModuleProcessFilter::Name($name),
),
}
};
(@mode_expr { user, process = $($path:tt)+ } turbofish: { $($tf:tt)* }) => {
$crate::reactor::ModuleMode::User {
process: ::std::option::Option::Some(
$crate::reactor::ModuleProcessFilter::Predicate(&$($path)+ $($tf)*),
),
}
};
(
@emit_resolver
name: [$name:ident]
variants: $variants:tt
resolver: { no }
cache: { no }
) => { };
(
@emit_resolver
name: [$name:ident]
variants: {
$( { variant: $variant:ident, name: $mod_name:literal, optional: $opt:tt } )*
}
resolver: { yes $rvis:vis $resolver:ident }
cache: { no }
) => {
$crate::_private_define_modules! {
@emit_resolver_struct
name: [$name]
variants: { $( { variant: $variant, name: $mod_name, optional: $opt } )* }
resolver: { $rvis $resolver }
}
};
(
@emit_resolver
name: [$name:ident]
variants: {
$( { variant: $variant:ident, name: $mod_name:literal, optional: $opt:tt } )*
}
resolver: { yes $rvis:vis $resolver:ident }
cache: { yes $cvis:vis $cache:ident }
) => {
$crate::_private_define_modules! {
@emit_resolver_struct
name: [$name]
variants: { $( { variant: $variant, name: $mod_name, optional: $opt } )* }
resolver: { $rvis $resolver }
}
#[doc = concat!(
"Cache for resolved symbol entries of `", stringify!($name), "`.\n\n",
"Slot 0 is reserved for the kernel. The remaining slots correspond to ",
"the modules of the enum, indexed by `slot()`."
)]
$cvis struct $cache {
__inner: [
::std::option::Option<
$crate::reactor::macros::__private::isr_cache::Entry
>;
1 + <[()]>::len(&[ $( $crate::_private_modules_unit!($variant) ),* ])
],
}
impl ::std::default::Default for $cache {
fn default() -> Self {
Self {
__inner: [
const { ::std::option::Option::None };
1 + <[()]>::len(&[ $( $crate::_private_modules_unit!($variant) ),* ])
],
}
}
}
#[allow(dead_code)]
impl<'a, __Driver> $resolver<'a, $crate::reactor::macros::__private::vmi_os_windows::WindowsOs<__Driver>>
where
__Driver: $crate::reactor::macros::__private::vmi_core::driver::VmiFullDriver,
__Driver::Architecture:
$crate::reactor::macros::__private::vmi_os_windows::ArchAdapter<__Driver> +
$crate::resolver::ArchAdapter<__Driver>,
{
pub fn resolve(
mut self,
session: &$crate::reactor::macros::__private::vmi_core::VmiSession<
$crate::reactor::macros::__private::vmi_os_windows::WindowsOs<__Driver>
>,
isr: &$crate::reactor::macros::__private::isr_cache::IsrCache,
entries: &'a mut $cache,
) -> ::std::result::Result<
Self,
$crate::reactor::macros::__private::vmi_core::VmiError,
> {
$crate::reactor::macros::__private::resolve_modules::<__Driver, $name>(
session,
isr,
entries.__inner.as_mut_slice(),
self.__inner.as_mut_slice(),
)?;
::std::result::Result::Ok(self)
}
}
};
(
@emit_resolver_struct
name: [$name:ident]
variants: {
$( { variant: $variant:ident, name: $mod_name:literal, optional: $opt:tt } )*
}
resolver: { $rvis:vis $resolver:ident }
) => {
#[doc = concat!(
"Table of resolved modules for `", stringify!($name), "`.\n\n",
"Slot 0 is reserved for the kernel; the remaining slots correspond to ",
"the variants of the enum, indexed by `slot()`.\n\n",
"The `Os` parameter is locked when `.resolve(...)` is called against a ",
"concrete `VmiSession<Os>`; before that point inference will leave it open."
)]
$rvis struct $resolver<'a, __Os>
where
__Os: $crate::reactor::macros::__private::vmi_core::VmiOs + 'static,
{
__inner: [
::std::option::Option<$crate::reactor::ResolvedModule<'a>>;
1 + <[()]>::len(&[ $( $crate::_private_modules_unit!($variant) ),* ])
],
__marker: ::std::marker::PhantomData<fn() -> __Os>,
}
impl<'a, __Os> ::std::default::Default for $resolver<'a, __Os>
where
__Os: $crate::reactor::macros::__private::vmi_core::VmiOs + 'static,
{
fn default() -> Self {
Self {
__inner: [
const { ::std::option::Option::None };
1 + <[()]>::len(&[ $( $crate::_private_modules_unit!($variant) ),* ])
],
__marker: ::std::marker::PhantomData,
}
}
}
#[allow(dead_code)]
impl<'a, __Os> $resolver<'a, __Os>
where
__Os: $crate::reactor::macros::__private::vmi_core::VmiOs + 'static,
$name: $crate::reactor::ReactorModule<__Os>,
{
pub fn with_kernel(
mut self,
base_address: $crate::reactor::macros::__private::vmi_core::Va,
profile: impl ::std::convert::Into<$crate::reactor::ProfileRef<'a>>,
) -> Self {
let profile = profile.into();
self.__inner[<$name as $crate::reactor::ReactorModule<__Os>>::KERNEL_SLOT] =
::std::option::Option::Some(
$crate::reactor::ResolvedModule { process: None, base_address, profile },
);
self
}
pub fn with_module(
mut self,
module: $name,
base_address: $crate::reactor::macros::__private::vmi_core::Va,
profile: impl ::std::convert::Into<$crate::reactor::ProfileRef<'a>>,
) -> Self {
let profile = profile.into();
let slot = <$name as $crate::reactor::ReactorModule<__Os>>::slot(module);
self.__inner[slot] = ::std::option::Option::Some(
$crate::reactor::ResolvedModule { process: None, base_address, profile },
);
self
}
pub fn with_module_in_process(
mut self,
module: $name,
process: $crate::reactor::macros::__private::vmi_core::os::ProcessObject,
base_address: $crate::reactor::macros::__private::vmi_core::Va,
profile: impl ::std::convert::Into<$crate::reactor::ProfileRef<'a>>,
) -> Self {
let profile = profile.into();
let slot = <$name as $crate::reactor::ReactorModule<__Os>>::slot(module);
self.__inner[slot] = ::std::option::Option::Some(
$crate::reactor::ResolvedModule { process: Some(process), base_address, profile },
);
self
}
pub fn into_events<Event>(
self,
) -> ::std::result::Result<
::std::vec::Vec<$crate::reactor::ResolvedEvent<Event>>,
$crate::reactor::macros::__private::vmi_core::VmiError,
>
where
Event: $crate::reactor::ReactorEvent<Module = $name>,
{
$crate::reactor::macros::__private::resolve_events::<Event, __Os>(
self.__inner.as_slice(),
)
}
}
};
}