blob: 7dbd4eacb54ae5a323e01fc07f97fa5a76305fc7 [file] [log] [blame]
mod impls;
/// A trait to perform in-order, serial, byte-wise I/O.
///
/// When the `std` feature is enabled, this trait is automatically implemented
/// for [`TcpStream`](std::net::TcpStream) and
/// [`UnixStream`](std::os::unix::net::UnixStream) (on unix systems).
pub trait Connection {
/// Transport-specific error type.
type Error;
/// Read a single byte.
fn read(&mut self) -> Result<u8, Self::Error>;
/// Read the exact number of bytes required to fill the buffer.
///
/// This method's default implementation calls `self.read()` for each byte
/// in the buffer. This can be quite inefficient, so if a more efficient
/// implementation exists (such as calling `read_exact()` on an underlying
/// `std::io::Read` object), this method should be overwritten.
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
for b in buf {
*b = self.read()?;
}
Ok(())
}
/// Write a single byte.
fn write(&mut self, byte: u8) -> Result<(), Self::Error>;
/// Write the entire buffer, blocking until complete.
///
/// This method's default implementation calls `self.write()` on each byte
/// in the buffer. This can be quite inefficient, so if a more efficient
/// implementation exists (such as calling `write_all()` on an underlying
/// `std::io::Write` object), this method should be overwritten.
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
for b in buf {
self.write(*b)?;
}
Ok(())
}
/// Peek a single byte. This MUST be a **non-blocking** operation, returning
/// `None` if no byte is available.
fn peek(&mut self) -> Result<Option<u8>, Self::Error>;
/// Flush this Connection, ensuring that all intermediately buffered
/// contents reach their destination.
///
/// _Note:_ Not all `Connection`s have internal buffering (e.g: writing data
/// to a UART TX register with FIFOs disabled). In these cases, it's fine to
/// simply return `Ok(())`.
fn flush(&mut self) -> Result<(), Self::Error>;
/// Called at the start of a debugging session _before_ any GDB packets have
/// been sent/received.
///
/// This method's default implementation is a no-op.
///
/// # Example
///
/// The `on_session_start` implementation for `TcpStream` ensures that
/// [`set_nodelay(true)`](std::net::TcpStream::set_nodelay)
/// is called. The GDB remote serial protocol requires sending/receiving
/// many small packets, so forgetting to enable `TCP_NODELAY` can result in
/// a massively degraded debugging experience.
fn on_session_start(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}