1use crate::Standard;
2use alloc::{boxed::Box, string::String, vec::Vec};
3use core::{num::NonZeroUsize, pin::Pin};
4use file_system::{
5 ControlCommand, ControlCommandIdentifier, DirectBaseOperations, DirectCharacterDevice,
6 MountOperations, define_command,
7};
8use shared::AnyByLayout;
9
10define_command!(GET_MAIN_FUNCTION, Read, b'E', 1, (), MainFunction);
11
12pub trait ExecutableTrait: 'static + Send + Sync {
13 fn main(standard: Standard, arguments: Vec<String>) -> MainFuture;
14}
15
16pub type MainFuture =
17 Pin<Box<dyn Future<Output = core::result::Result<(), NonZeroUsize>> + 'static>>;
18
19pub type MainFunction = Option<Box<dyn Fn(Standard, Vec<String>) -> MainFuture + 'static>>;
20
21pub struct ExecutableWrapper<T: ExecutableTrait>(T);
22
23impl<T: ExecutableTrait> ExecutableWrapper<T> {
24 pub fn new(executable: T) -> Self {
25 Self(executable)
26 }
27}
28
29impl<T: ExecutableTrait> MountOperations for ExecutableWrapper<T> {}
30
31impl<T: ExecutableTrait> DirectBaseOperations for ExecutableWrapper<T> {
32 fn read(
33 &self,
34 _buffer: &mut [u8],
35 _absolute_position: file_system::Size,
36 ) -> file_system::Result<usize> {
37 Err(file_system::Error::UnsupportedOperation)
38 }
39
40 fn write(
41 &self,
42 _buffer: &[u8],
43 _absolute_position: file_system::Size,
44 ) -> file_system::Result<usize> {
45 Err(file_system::Error::UnsupportedOperation)
46 }
47
48 fn control(
49 &self,
50 command: ControlCommandIdentifier,
51 _: &AnyByLayout,
52 output: &mut AnyByLayout,
53 ) -> file_system::Result<()> {
54 log::debug!("ExecutableWrapper control command: {:?}", command);
55
56 match command {
57 GET_MAIN_FUNCTION::IDENTIFIER => {
58 let output = GET_MAIN_FUNCTION::cast_output(output)?;
59 *output = Some(Box::new(T::main));
60 Ok(())
61 }
62 _ => Err(file_system::Error::UnsupportedOperation),
63 }
64 }
65}
66
67impl<T: ExecutableTrait> DirectCharacterDevice for ExecutableWrapper<T> {}
68
69#[macro_export]
70macro_rules! mount_executables {
71
72 ( $virtual_file_system:expr, $task:expr, &[ $( ($path:expr, $executable:expr) ),* $(,)? ] ) => {
73
74 async || -> $crate::exported_virtual_file_system::Result<()>
75 {
76 use $crate::exported_file_system::{Permissions};
77 use $crate::exported_virtual_file_system::ItemStatic;
78
79 $(
80 let __executable = $crate::ExecutableWrapper::new($executable);
81
82 let _ = $virtual_file_system.remove($task, $path).await;
83 $virtual_file_system.mount_character_device($task, $path, __executable).await?;
84 $virtual_file_system.set_permissions($task, $path, Permissions::EXECUTABLE).await?;
85 )*
86
87 Ok(())
88 }()
89};
90
91}