use crate::protocol::commands::ParseCommand; use crate::protocol::common::hex::decode_hex; use crate::protocol::packet::PacketBuf; /// Parse the `annex` field of a qXfer packet. Used in conjunction with /// `QXferBase` to cut keep qXfer packet parsing DRY. pub trait ParseAnnex<'a>: Sized { fn from_buf(buf: &'a [u8]) -> Option; } #[derive(Debug)] pub struct QXferReadBase<'a, T: ParseAnnex<'a>> { pub annex: T, pub offset: u64, pub length: usize, pub buf: &'a mut [u8], } impl<'a, T: ParseAnnex<'a>> ParseCommand<'a> for QXferReadBase<'a, T> { #[inline(always)] fn from_packet(buf: PacketBuf<'a>) -> Option { let (buf, body_range) = buf.into_raw_buf(); // this looks a bit wacky, but the compiler is dumb and won't elide bounds // checks without it. let (body, buf) = { let buf = buf.get_mut(body_range.start..)?; if body_range.end - body_range.start > buf.len() { return None; } buf.split_at_mut(body_range.end - body_range.start) }; if body.is_empty() { return None; } let mut body = body.split(|b| *b == b':').skip(1); let annex = T::from_buf(body.next()?)?; let mut body = body.next()?.split(|b| *b == b','); let offset = decode_hex(body.next()?).ok()?; let length = decode_hex(body.next()?).ok()?; Some(QXferReadBase { annex, offset, length, buf, }) } }