executable/
device_trait.rs

1use alloc::string::String;
2use file_system::DeviceTrait;
3use task::TaskIdentifier;
4use virtual_file_system::VirtualFileSystem;
5
6pub trait DeviceExecutableTrait: DeviceTrait {
7    fn mount<'a>(
8        virtual_file_system: &'a VirtualFileSystem<'a>,
9        task: TaskIdentifier,
10    ) -> Result<(), String>;
11}
12
13/// Macro to automatically implement DeviceExecutableTrait for a struct with a main function.
14///
15/// This macro generates both the DeviceExecutableTrait implementation and the DeviceTrait
16/// implementation for executable devices.
17///
18/// # Usage
19///
20/// For simple executables:
21/// ```rust
22/// extern crate alloc;
23///
24/// pub struct MyExecutableType;
25///
26/// async fn my_main_function(
27///     standard: executable::Standard,
28///     arguments: String
29/// ) -> Result<(), core::num::NonZeroUsize> {
30///    standard.print_line(&arguments);
31///
32///    Ok(())
33/// }
34///
35/// executable::implement_executable_device!(
36///     Structure: MyExecutableType,
37///     Mount_path: "/binaries/MyExecutable",
38///     Main_function: my_main_function,
39/// );
40/// ```
41#[macro_export]
42macro_rules! implement_executable_device {
43    // Simple executable without constructor
44    (
45        Structure: $struct_name:ident,
46        Mount_path: $mount_path:expr,
47        Main_function: $main_function:path,
48    ) => {
49        impl executable::DeviceExecutableTrait for $struct_name {
50            fn mount<'a>(
51                virtual_file_system: &'a virtual_file_system::VirtualFileSystem<'a>,
52                task: task::TaskIdentifier,
53            ) -> core::result::Result<(), alloc::string::String> {
54                use alloc::string::ToString;
55
56                futures::block_on(virtual_file_system.mount_static_device(
57                    task,
58                    &$mount_path,
59                    file_system::create_device!($struct_name),
60                ))
61                .map_err(|error| error.to_string())?;
62
63                Ok(())
64            }
65        }
66
67        impl file_system::DeviceTrait for $struct_name {
68            fn read(&self, buffer: &mut [u8]) -> file_system::Result<file_system::Size> {
69                let read_data: &mut executable::ReadData = buffer
70                    .try_into()
71                    .map_err(|_| file_system::Error::InvalidParameter)?;
72
73                *read_data = executable::ReadData::new($main_function);
74
75                Ok(core::mem::size_of::<executable::ReadData>().into())
76            }
77
78            fn write(&self, _: &[u8]) -> file_system::Result<file_system::Size> {
79                Err(file_system::Error::UnsupportedOperation)
80            }
81
82            fn get_size(&self) -> file_system::Result<file_system::Size> {
83                Err(file_system::Error::UnsupportedOperation)
84            }
85
86            fn set_position(
87                &self,
88                _: &file_system::Position,
89            ) -> file_system::Result<file_system::Size> {
90                Err(file_system::Error::UnsupportedOperation)
91            }
92
93            fn flush(&self) -> file_system::Result<()> {
94                Err(file_system::Error::UnsupportedOperation)
95            }
96        }
97    };
98}
99
100#[macro_export]
101macro_rules! mount_static_executables {
102
103    ( $Virtual_file_system:expr, $Task_identifier:expr, &[ $( ($Path:expr, $Device:expr) ),* $(,)? ] ) => {
104
105    async || -> Result<(), file_system::Error>
106    {
107        use file_system::{create_device, Permissions};
108
109        $(
110            $Virtual_file_system.mount_static_device($Task_identifier, $Path, create_device!($Device)).await?;
111            $Virtual_file_system.set_permissions($Path, Permissions::EXECUTABLE ).await?;
112        )*
113
114        Ok(())
115    }()
116};
117
118}