imgui_terminal/
lib.rs

1#[cxx::bridge(namespace = "terminal")]
2mod ffi {
3    // Any shared structs, whose fields will be visible to both languages.
4
5    // extern "Rust" {
6    //     // Zero or more opaque types which both lagnauges can pass around but only Rust can see the
7    //     // fields.
8
9    //     // type MultiBuf;
10
11    //     // Functions implemented in rust.
12    //     // fn next_chunk(buf: &mut MultiBuf) -> &[u8];
13    // }
14
15    unsafe extern "C++" {
16        // One or more headers with the matching C++ declarations.  Our code generators don't read
17        // it but it gets #include'd and used in static assertions to ensure our picture of the FFI
18        // boundary is accurate.
19        include!("imgui-terminal-rs.h");
20
21        // Zero or more opaque types which both languages can pass around but only C++ can see the
22        // fields.
23        type Terminal;
24
25        // Functions implemented in C++.
26        fn new_terminal() -> UniquePtr<Terminal>;
27        fn reset(self: Pin<&mut Terminal>);
28        fn draw_term(terminal: Pin<&mut Terminal>, str_id: String, p_open: &mut bool);
29        fn write_term(terminal: Pin<&mut Terminal>, bytes: &str);
30        fn read_term(terminal: Pin<&mut Terminal>, bytes: &mut [u8]) -> i32;
31    }
32}
33
34pub struct Terminal {
35    inner: cxx::UniquePtr<ffi::Terminal>,
36}
37impl Terminal {
38    pub fn new() -> Option<Self> {
39        let inner = ffi::new_terminal();
40        if inner.is_null() {
41            return None;
42        }
43        Some(Self { inner: ffi::new_terminal() })
44    }
45    pub fn as_inner(&mut self) -> std::pin::Pin<&mut ffi::Terminal> {
46        self.inner.pin_mut()
47    }
48    /// Reset the terminal.
49    pub fn reset(&mut self) {
50        self.as_inner().reset()
51    }
52    /// Draw the terminal window.
53    ///
54    /// open is an out-parameter indicating whether the window is (still) open.
55    pub fn draw(&mut self, str_id: &imgui::ImStr, open: &mut bool) {
56        ffi::draw_term(self.as_inner(), str_id.to_string(), &mut *open)
57    }
58    /// Write characters to the terminal.
59    /// TODO: Is it correct to send rust utf8 slices like this?
60    pub fn write(&mut self, bytes: &str) {
61        ffi::write_term(self.as_inner(), bytes)
62    }
63
64    pub fn read(&mut self, buffer: &mut [u8]) -> i32 {
65        ffi::read_term(self.as_inner(), buffer)
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    #[test]
72    fn it_works() {
73        assert_eq!(2 + 2, 4);
74    }
75}