1 #[cfg(feature = "alloc")] 2 use alloc::string::String; 3 4 use num_traits::PrimInt; 5 6 use crate::internal::BeBytes; 7 use crate::protocol::{IdKind, ThreadId}; 8 use crate::Connection; 9 10 /// Newtype around a Connection error. Having a newtype allows implementing a 11 /// `From<ResponseWriterError<C>> for crate::Error<T, C>`, which greatly 12 /// simplifies some of the error handling in the main gdbstub. 13 #[derive(Debug, Clone)] 14 pub struct Error<C>(C); 15 16 /// A wrapper around [`Connection`] that computes the single-byte checksum of 17 /// incoming / outgoing data. 18 pub struct ResponseWriter<'a, C: Connection + 'a> { 19 inner: &'a mut C, 20 started: bool, 21 checksum: u8, 22 // buffer outgoing message 23 // TODO: add `write_all` method to Connection, and allow user to optionally pass outgoing 24 // packet buffer? This could improve performance (instead of writing a single byte at a time) 25 #[cfg(feature = "alloc")] 26 msg: String, 27 } 28 29 impl<'a, C: Connection + 'a> ResponseWriter<'a, C> { 30 /// Creates a new ResponseWriter new(inner: &'a mut C) -> Self31 pub fn new(inner: &'a mut C) -> Self { 32 Self { 33 inner, 34 started: false, 35 checksum: 0, 36 #[cfg(feature = "alloc")] 37 msg: String::new(), 38 } 39 } 40 41 /// Consumes self, writing out the final '#' and checksum flush(mut self) -> Result<(), Error<C::Error>>42 pub fn flush(mut self) -> Result<(), Error<C::Error>> { 43 // don't include '#' in checksum calculation 44 let checksum = self.checksum; 45 46 #[cfg(feature = "alloc")] 47 trace!("--> ${}#{:02x?}", self.msg, checksum); 48 49 self.write(b'#')?; 50 self.write_hex(checksum)?; 51 52 Ok(()) 53 } 54 55 /// Get a mutable reference to the underlying connection. as_conn(&mut self) -> &mut C56 pub fn as_conn(&mut self) -> &mut C { 57 self.inner 58 } 59 60 /// Write a single byte. write(&mut self, byte: u8) -> Result<(), Error<C::Error>>61 pub fn write(&mut self, byte: u8) -> Result<(), Error<C::Error>> { 62 #[cfg(feature = "alloc")] 63 self.msg.push(byte as char); 64 65 if !self.started { 66 self.started = true; 67 self.inner.write(b'$').map_err(Error)?; 68 } 69 70 self.checksum = self.checksum.wrapping_add(byte); 71 self.inner.write(byte).map_err(Error) 72 } 73 74 /// Write an entire buffer over the connection. write_all(&mut self, data: &[u8]) -> Result<(), Error<C::Error>>75 pub fn write_all(&mut self, data: &[u8]) -> Result<(), Error<C::Error>> { 76 data.iter().try_for_each(|b| self.write(*b)) 77 } 78 79 /// Write an entire string over the connection. write_str(&mut self, s: &str) -> Result<(), Error<C::Error>>80 pub fn write_str(&mut self, s: &str) -> Result<(), Error<C::Error>> { 81 self.write_all(&s.as_bytes()) 82 } 83 84 /// Write a single byte as a hex string (two ascii chars) write_hex(&mut self, byte: u8) -> Result<(), Error<C::Error>>85 fn write_hex(&mut self, byte: u8) -> Result<(), Error<C::Error>> { 86 for digit in [(byte & 0xf0) >> 4, byte & 0x0f].iter() { 87 let c = match digit { 88 0..=9 => b'0' + digit, 89 10..=15 => b'a' + digit - 10, 90 _ => unreachable!(), 91 }; 92 self.write(c)?; 93 } 94 Ok(()) 95 } 96 97 /// Write a byte-buffer as a hex string (i.e: two ascii chars / byte). write_hex_buf(&mut self, data: &[u8]) -> Result<(), Error<C::Error>>98 pub fn write_hex_buf(&mut self, data: &[u8]) -> Result<(), Error<C::Error>> { 99 data.iter().try_for_each(|b| self.write_hex(*b)) 100 } 101 102 /// Write data using the binary protocol. write_binary(&mut self, data: &[u8]) -> Result<(), Error<C::Error>>103 pub fn write_binary(&mut self, data: &[u8]) -> Result<(), Error<C::Error>> { 104 data.iter().try_for_each(|b| match b { 105 b'#' | b'$' | b'}' | b'*' => { 106 self.write(b'}')?; 107 self.write(*b ^ 0x20) 108 } 109 _ => self.write(*b), 110 }) 111 } 112 113 /// Write a number as a big-endian hex string using the most compact 114 /// representation possible (i.e: trimming leading zeros). write_num<D: BeBytes + PrimInt>(&mut self, digit: D) -> Result<(), Error<C::Error>>115 pub fn write_num<D: BeBytes + PrimInt>(&mut self, digit: D) -> Result<(), Error<C::Error>> { 116 if digit.is_zero() { 117 return self.write_hex(0); 118 } 119 120 let mut buf = [0; 16]; 121 // infallible (unless digit is a >128 bit number) 122 let len = digit.to_be_bytes(&mut buf).unwrap(); 123 let buf = &buf[..len]; 124 buf.iter() 125 .copied() 126 .skip_while(|&b| b == 0) 127 .try_for_each(|b| self.write_hex(b)) 128 } 129 write_id_kind(&mut self, tid: IdKind) -> Result<(), Error<C::Error>>130 pub fn write_id_kind(&mut self, tid: IdKind) -> Result<(), Error<C::Error>> { 131 match tid { 132 IdKind::All => self.write_str("-1")?, 133 IdKind::Any => self.write_str("0")?, 134 IdKind::WithID(id) => self.write_num(id.get())?, 135 }; 136 Ok(()) 137 } 138 write_thread_id(&mut self, tid: ThreadId) -> Result<(), Error<C::Error>>139 pub fn write_thread_id(&mut self, tid: ThreadId) -> Result<(), Error<C::Error>> { 140 if let Some(pid) = tid.pid { 141 self.write_str("p")?; 142 self.write_id_kind(pid)?; 143 self.write_str(".")?; 144 } 145 self.write_id_kind(tid.tid)?; 146 Ok(()) 147 } 148 } 149