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