use super::prelude::*; #[derive(Debug)] pub struct m<'a> { pub addr: &'a [u8], pub len: usize, pub buf: &'a mut [u8], } impl<'a> ParseCommand<'a> for m<'a> { #[inline(always)] fn from_packet(buf: PacketBuf<'a>) -> Option { // the total packet buffer currently looks like: // // +------+--------------------+-------------------+-------+-----------------+ // | "$m" | addr (hex-encoded) | len (hex-encoded) | "#XX" | empty space ... | // +------+--------------------+-------------------+-------+-----------------+ // // Unfortunately, while `len` can be hex-decoded right here and now into a // `usize`, `addr` corresponds to a Target::Arch::Usize, which requires holding // on to a valid &[u8] reference into the buffer. // // While it's not _perfectly_ efficient, simply leaving the decoded addr in // place and wasting a couple bytes is probably the easiest way to tackle this // problem: // // +------+------------------+------------------------------------------------+ // | "$m" | addr (raw bytes) | usable buffer ... | // +------+------------------+------------------------------------------------+ let (buf, body_range) = buf.into_raw_buf(); let body = buf.get_mut(body_range.start..body_range.end)?; let mut body = body.split_mut(|b| *b == b','); let addr = decode_hex_buf(body.next()?).ok()?; let addr_len = addr.len(); let len = decode_hex(body.next()?).ok()?; // ensures that `split_at_mut` doesn't panic if buf.len() < body_range.start + addr_len { return None; } let (addr, buf) = buf.split_at_mut(body_range.start + addr_len); let addr = addr.get(b"$m".len()..)?; Some(m { addr, len, buf }) } }