logboi/
lib.rs

1use secgate::util::{Descriptor, Handle, SimpleBuffer};
2use twizzler_rt_abi::{error::TwzError, object::MapFlags};
3
4/// An open handle to the logging service.
5pub struct LogHandle {
6    desc: Descriptor,
7    buffer: SimpleBuffer,
8}
9
10#[secgate::gatecall]
11pub fn logboi_open_handle() -> Result<(Descriptor, twizzler_rt_abi::object::ObjID), TwzError> {}
12#[secgate::gatecall]
13pub fn logboi_close_handle(desc: Descriptor) -> Result<(), TwzError> {}
14#[secgate::gatecall]
15pub fn logboi_post(desc: Descriptor, buf_len: usize) -> Result<(), TwzError> {}
16
17// A service typically implements these handles via this interface.
18// You can see that internally, this is where most of the secure gate APIs
19// are actually used, so that interface is abstracted from the programmer.
20impl Handle for LogHandle {
21    type OpenError = TwzError;
22
23    type OpenInfo = ();
24
25    fn open(_info: Self::OpenInfo) -> Result<Self, Self::OpenError>
26    where
27        Self: Sized,
28    {
29        let (desc, id) = logboi_open_handle()?;
30        let handle =
31            twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::READ | MapFlags::WRITE)?;
32        let sb = SimpleBuffer::new(handle);
33        Ok(Self { desc, buffer: sb })
34    }
35
36    fn release(&mut self) {
37        let _ = logboi_close_handle(self.desc);
38    }
39}
40
41// On drop, release the handle.
42impl Drop for LogHandle {
43    fn drop(&mut self) {
44        self.release()
45    }
46}
47
48impl LogHandle {
49    /// Open a new logging handle.
50    pub fn new() -> Option<Self> {
51        Self::open(()).ok()
52    }
53
54    /// Send a log message via this logging handle.
55    pub fn log(&mut self, buf: &[u8]) -> Option<usize> {
56        let len = self.buffer.write(buf);
57        if len == 0 {
58            return Some(0);
59        }
60
61        if logboi_post(self.desc, len).ok().is_some() {
62            Some(len)
63        } else {
64            None
65        }
66    }
67}