safa_api/
lib.rs

1//! A high-level API over SafaOS's syscalls
2//!
3//! for example [`self::alloc`] is a high-level userspace allocator which internally uses the [`self::syscalls::syssbrk`] syscall
4//!
5//! This crate also exposes raw SafaOS syscalls (see [`self::syscalls`])
6//! and raw SafaOS abi structures (see [`self::raw`])
7
8#![cfg_attr(not(feature = "std"), no_std)]
9
10use core::{cell::LazyCell, fmt::Write, ops::Deref};
11
12use crate::process::stdio::sysget_stderr;
13
14pub mod errors {
15    pub use safa_abi::errors::{ErrorStatus, SysResult};
16
17    #[cfg(any(feature = "rustc-dep-of-std", feature = "std"))]
18    #[cfg_attr(feature = "rustc-dep-of-std", macro_export)]
19    macro_rules! err_from_io_error_kind {
20        ($io_err_ty: path, $io_err: ident) => {
21            use $crate::errors::ErrorStatus::*;
22            use $io_err_ty as IoErrorKind;
23
24            return match $io_err {
25                IoErrorKind::NotFound => NoSuchAFileOrDirectory,
26                IoErrorKind::AlreadyExists => AlreadyExists,
27                IoErrorKind::PermissionDenied => MissingPermissions,
28                IoErrorKind::ResourceBusy => Busy,
29                IoErrorKind::NotADirectory => NotADirectory,
30                IoErrorKind::IsADirectory => NotAFile,
31                IoErrorKind::OutOfMemory => OutOfMemory,
32                IoErrorKind::Other => Generic,
33                IoErrorKind::DirectoryNotEmpty => DirectoryNotEmpty,
34                IoErrorKind::Unsupported => OperationNotSupported,
35
36                _ => Generic,
37            };
38        };
39    }
40
41    #[cfg(feature = "std")]
42    pub fn err_from_io_error_kind(io_err: std::io::ErrorKind) -> ErrorStatus {
43        err_from_io_error_kind!(std::io::ErrorKind, io_err);
44    }
45}
46
47pub mod alloc;
48pub mod process;
49pub mod raw;
50pub mod syscalls;
51
52// FIXME: introduce locks when threads are added
53pub(crate) struct Lazy<T>(core::cell::LazyCell<T>);
54impl<T> Lazy<T> {
55    pub const fn new(value: fn() -> T) -> Self {
56        Self(core::cell::LazyCell::new(value))
57    }
58}
59
60impl<T> Deref for Lazy<T> {
61    type Target = LazyCell<T>;
62    fn deref(&self) -> &Self::Target {
63        &self.0
64    }
65}
66
67unsafe impl<T> Sync for Lazy<T> {}
68unsafe impl<T> Send for Lazy<T> {}
69
70#[allow(unused)]
71struct Stderr;
72
73fn _print_err(str: &str) {
74    let stderr = sysget_stderr();
75    _ = syscalls::io::write(stderr, -1, str.as_bytes());
76    _ = syscalls::io::sync(stderr);
77}
78impl Write for Stderr {
79    fn write_str(&mut self, s: &str) -> core::fmt::Result {
80        _print_err(s);
81        Ok(())
82    }
83}
84
85#[allow(unused)]
86macro_rules! printerr {
87    ($($arg:tt)*) => {
88        _ = Stderr.write_fmt(format_args!($($arg)*));
89    };
90}
91
92#[allow(unused)]
93macro_rules! printerrln {
94    () => {
95        printerr!("\n");
96    };
97    ($($arg:tt)*) => {
98        printerr!("{}\n", format_args!($($arg)*));
99    };
100}
101
102#[cfg(not(any(feature = "std", feature = "rustc-dep-of-std")))]
103#[panic_handler]
104fn _panic(info: &core::panic::PanicInfo) -> ! {
105    printerrln!("Safa-API panicked: {}", info);
106    syscalls::process::exit(1);
107}