Skip to main content

airbender_guest/
transport.rs

1//! Word-based transports for guest communication.
2
3/// Word-based transport used by the guest to communicate with the host.
4pub trait Transport {
5    fn read_word(&mut self) -> u32;
6    fn write_word(&mut self, word: u32);
7}
8
9/// CSR-backed transport for real guest execution.
10pub struct CsrTransport;
11
12#[cfg(target_arch = "riscv32")]
13impl Transport for CsrTransport {
14    fn read_word(&mut self) -> u32 {
15        airbender_rt::sys::read_word()
16    }
17
18    fn write_word(&mut self, word: u32) {
19        airbender_rt::sys::write_word(word);
20    }
21}
22
23#[cfg(not(target_arch = "riscv32"))]
24impl Transport for CsrTransport {
25    fn read_word(&mut self) -> u32 {
26        panic!("csr transport is only available on riscv32")
27    }
28
29    fn write_word(&mut self, _word: u32) {
30        panic!("csr transport is only available on riscv32")
31    }
32}
33
34/// In-memory transport for unit tests and host-side checks.
35#[derive(Default)]
36pub struct MockTransport {
37    reads: alloc::vec::Vec<u32>,
38    writes: alloc::vec::Vec<u32>,
39    cursor: usize,
40}
41
42impl MockTransport {
43    /// Create a mock transport seeded with preloaded read words.
44    pub fn new(reads: alloc::vec::Vec<u32>) -> Self {
45        Self {
46            reads,
47            writes: alloc::vec::Vec::new(),
48            cursor: 0,
49        }
50    }
51
52    /// Append additional read words to the transport.
53    pub fn push_reads(&mut self, words: impl IntoIterator<Item = u32>) {
54        self.reads.extend(words);
55    }
56
57    /// Inspect words written by the guest.
58    pub fn writes(&self) -> &[u32] {
59        &self.writes
60    }
61
62    /// Consume the transport and return captured writes.
63    pub fn into_writes(self) -> alloc::vec::Vec<u32> {
64        self.writes
65    }
66}
67
68impl Transport for MockTransport {
69    fn read_word(&mut self) -> u32 {
70        let Some(word) = self.reads.get(self.cursor) else {
71            panic!("mock transport exhausted");
72        };
73        self.cursor += 1;
74        *word
75    }
76
77    fn write_word(&mut self, word: u32) {
78        self.writes.push(word);
79    }
80}