executable/
traits.rs

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}