1 //! Traits to perform in-order, serial, byte-wise I/O. 2 3 mod impls; 4 5 /// A trait to perform in-order, serial, byte-wise I/O. 6 /// 7 /// When the `std` feature is enabled, this trait is automatically implemented 8 /// for [`TcpStream`](std::net::TcpStream) and 9 /// [`UnixStream`](std::os::unix::net::UnixStream) (on unix systems). 10 pub trait Connection { 11 /// Transport-specific error type. 12 type Error; 13 14 /// Write a single byte. write(&mut self, byte: u8) -> Result<(), Self::Error>15 fn write(&mut self, byte: u8) -> Result<(), Self::Error>; 16 17 /// Write the entire buffer, blocking until complete. 18 /// 19 /// This method's default implementation calls `self.write()` on each byte 20 /// in the buffer. This can be quite inefficient, so if a more efficient 21 /// implementation exists (such as calling `write_all()` on an underlying 22 /// `std::io::Write` object), this method should be overwritten. write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>23 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 24 for b in buf { 25 self.write(*b)?; 26 } 27 Ok(()) 28 } 29 30 /// Flush this Connection, ensuring that all intermediately buffered 31 /// contents reach their destination. 32 /// 33 /// _Note:_ Not all `Connection`s have internal buffering (e.g: writing data 34 /// to a UART TX register with FIFOs disabled). In these cases, it's fine to 35 /// simply return `Ok(())`. flush(&mut self) -> Result<(), Self::Error>36 fn flush(&mut self) -> Result<(), Self::Error>; 37 38 /// Called at the start of a debugging session _before_ any GDB packets have 39 /// been sent/received. 40 /// 41 /// This method's default implementation is a no-op. 42 /// 43 /// # Example 44 /// 45 /// The `on_session_start` implementation for `TcpStream` ensures that 46 /// [`set_nodelay(true)`](std::net::TcpStream::set_nodelay) 47 /// is called. The GDB remote serial protocol requires sending/receiving 48 /// many small packets, so forgetting to enable `TCP_NODELAY` can result in 49 /// a massively degraded debugging experience. on_session_start(&mut self) -> Result<(), Self::Error>50 fn on_session_start(&mut self) -> Result<(), Self::Error> { 51 Ok(()) 52 } 53 } 54 55 /// Extends [`Connection`] with `read` and `peek` methods. 56 /// 57 /// This trait is used as part of `gdbstub`'s quickstart 58 /// [`GdbStub::run_blocking`](crate::stub::GdbStub::run_blocking) API. 59 /// 60 /// When the `std` feature is enabled, this trait is automatically implemented 61 /// for [`TcpStream`](std::net::TcpStream) and 62 /// [`UnixStream`](std::os::unix::net::UnixStream) (on unix systems). 63 /// 64 /// [`gdbstub_run::Callbacks::read_byte`]: 65 /// crate::gdbstub_run::Callbacks::read_byte 66 pub trait ConnectionExt: Connection { 67 /// Read a single byte. read(&mut self) -> Result<u8, Self::Error>68 fn read(&mut self) -> Result<u8, Self::Error>; 69 70 /// Peek a single byte. This MUST be a **non-blocking** operation, returning 71 /// `None` if no byte is available. 72 /// 73 /// Returns a byte (if one is available) without removing that byte from the 74 /// queue. Subsequent calls to `peek` MUST return the same byte. peek(&mut self) -> Result<Option<u8>, Self::Error>75 fn peek(&mut self) -> Result<Option<u8>, Self::Error>; 76 } 77