• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::prelude::*;
2 
3 // TODO?: instead of parsing lazily when invoked, parse the strings into a
4 // compressed binary representations that can be stuffed back into the packet
5 // buffer, and return an iterator over the binary data that's _guaranteed_ to be
6 // valid. This would clean up some of the code in the vCont handler.
7 //
8 // The interesting part would be to see whether or not the simplified error
9 // handing code will compensate for all the new code required to pre-validate
10 // the data...
11 #[derive(Debug)]
12 pub enum vCont<'a> {
13     Query,
14     Actions(Actions<'a>),
15 }
16 
17 impl<'a> ParseCommand<'a> for vCont<'a> {
from_packet(buf: PacketBuf<'a>) -> Option<Self>18     fn from_packet(buf: PacketBuf<'a>) -> Option<Self> {
19         let body = buf.into_body();
20         match body as &[u8] {
21             b"?" => Some(vCont::Query),
22             _ => Some(vCont::Actions(Actions::new_from_buf(body))),
23         }
24     }
25 }
26 
27 #[derive(Debug)]
28 pub enum Actions<'a> {
29     Buf(ActionsBuf<'a>),
30     FixedStep(SpecificThreadId),
31     FixedCont(SpecificThreadId),
32 }
33 
34 impl<'a> Actions<'a> {
new_from_buf(buf: &'a [u8]) -> Actions<'a>35     fn new_from_buf(buf: &'a [u8]) -> Actions<'a> {
36         Actions::Buf(ActionsBuf(buf))
37     }
38 
new_step(tid: SpecificThreadId) -> Actions<'a>39     pub fn new_step(tid: SpecificThreadId) -> Actions<'a> {
40         Actions::FixedStep(tid)
41     }
42 
new_continue(tid: SpecificThreadId) -> Actions<'a>43     pub fn new_continue(tid: SpecificThreadId) -> Actions<'a> {
44         Actions::FixedCont(tid)
45     }
46 
iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_47     pub fn iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_ {
48         match self {
49             Actions::Buf(x) => EitherIter::A(x.iter()),
50             Actions::FixedStep(x) => EitherIter::B(core::iter::once(Some(VContAction {
51                 kind: VContKind::Step,
52                 thread: Some(*x),
53             }))),
54             Actions::FixedCont(x) => EitherIter::B(core::iter::once(Some(VContAction {
55                 kind: VContKind::Continue,
56                 thread: Some(*x),
57             }))),
58         }
59     }
60 }
61 
62 #[derive(Debug)]
63 pub struct ActionsBuf<'a>(&'a [u8]);
64 
65 impl<'a> ActionsBuf<'a> {
iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_66     fn iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_ {
67         self.0.split(|b| *b == b';').skip(1).map(|act| {
68             let mut s = act.split(|b| *b == b':');
69             let kind = s.next()?;
70             let thread = match s.next() {
71                 Some(s) => Some(SpecificThreadId::try_from(ThreadId::try_from(s).ok()?).ok()?),
72                 None => None,
73             };
74 
75             Some(VContAction {
76                 kind: VContKind::from_bytes(kind)?,
77                 thread,
78             })
79         })
80     }
81 }
82 
83 #[derive(Debug, Copy, Clone)]
84 pub struct VContAction<'a> {
85     pub kind: VContKind<'a>,
86     pub thread: Option<SpecificThreadId>,
87 }
88 
89 #[derive(Debug, Copy, Clone)]
90 pub enum VContKind<'a> {
91     Continue,
92     ContinueWithSig(u8),
93     RangeStep(HexString<'a>, HexString<'a>),
94     Step,
95     StepWithSig(u8),
96     Stop,
97 }
98 
99 impl<'a> VContKind<'a> {
from_bytes(s: &[u8]) -> Option<VContKind>100     fn from_bytes(s: &[u8]) -> Option<VContKind> {
101         use self::VContKind::*;
102 
103         let res = match s {
104             [b'c'] => Continue,
105             [b's'] => Step,
106             [b't'] => Stop,
107             [b'C', sig @ ..] => ContinueWithSig(decode_hex(sig).ok()?),
108             [b'S', sig @ ..] => StepWithSig(decode_hex(sig).ok()?),
109             [b'r', range @ ..] => {
110                 let mut range = range.split(|b| *b == b',');
111                 RangeStep(HexString(range.next()?), HexString(range.next()?))
112             }
113             _ => return None,
114         };
115 
116         Some(res)
117     }
118 }
119 
120 /// Helper type to unify iterators that output the same type. Returned as an
121 /// opaque type from `Actions::iter()`.
122 enum EitherIter<A, B> {
123     A(A),
124     B(B),
125 }
126 
127 impl<A, B, T> Iterator for EitherIter<A, B>
128 where
129     A: Iterator<Item = T>,
130     B: Iterator<Item = T>,
131 {
132     type Item = T;
next(&mut self) -> Option<T>133     fn next(&mut self) -> Option<T> {
134         match self {
135             EitherIter::A(a) => a.next(),
136             EitherIter::B(b) => b.next(),
137         }
138     }
139 }
140