1 use crate::protocol::commands::ParseCommand;
2 use crate::protocol::common::hex::decode_hex;
3 use crate::protocol::packet::PacketBuf;
4 
5 /// Parse the `annex` field of a qXfer packet. Used in conjunction with
6 /// `QXferBase` to cut keep qXfer packet parsing DRY.
7 pub trait ParseAnnex<'a>: Sized {
from_buf(buf: &'a [u8]) -> Option<Self>8     fn from_buf(buf: &'a [u8]) -> Option<Self>;
9 }
10 
11 #[derive(Debug)]
12 pub struct QXferReadBase<'a, T: ParseAnnex<'a>> {
13     pub annex: T,
14     pub offset: u64,
15     pub length: usize,
16 
17     pub buf: &'a mut [u8],
18 }
19 
20 impl<'a, T: ParseAnnex<'a>> ParseCommand<'a> for QXferReadBase<'a, T> {
21     #[inline(always)]
from_packet(buf: PacketBuf<'a>) -> Option<Self>22     fn from_packet(buf: PacketBuf<'a>) -> Option<Self> {
23         let (buf, body_range) = buf.into_raw_buf();
24 
25         // this looks a bit wacky, but the compiler is dumb and won't elide bounds
26         // checks without it.
27         let (body, buf) = {
28             let buf = buf.get_mut(body_range.start..)?;
29             if body_range.end - body_range.start > buf.len() {
30                 return None;
31             }
32             buf.split_at_mut(body_range.end - body_range.start)
33         };
34 
35         if body.is_empty() {
36             return None;
37         }
38 
39         let mut body = body.split(|b| *b == b':').skip(1);
40         let annex = T::from_buf(body.next()?)?;
41 
42         let mut body = body.next()?.split(|b| *b == b',');
43         let offset = decode_hex(body.next()?).ok()?;
44         let length = decode_hex(body.next()?).ok()?;
45 
46         Some(QXferReadBase {
47             annex,
48             offset,
49             length,
50             buf,
51         })
52     }
53 }
54