blob: af27ae285360ede7734b72b7c3a93ea438a70c0e [file] [log] [blame]
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<Self>;
}
#[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<Self> {
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,
})
}
}