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