1 use core::convert::{TryFrom, TryInto}; 2 use core::num::NonZeroUsize; 3 4 use super::decode_hex; 5 6 /// Tid/Pid Selector. 7 #[derive(PartialEq, Eq, Debug, Clone, Copy)] 8 pub enum IdKind { 9 /// All threads (-1) 10 All, 11 /// Any thread (0) 12 Any, 13 /// Thread with specific ID (id > 0) 14 WithID(NonZeroUsize), 15 } 16 17 /// Unique Thread ID. 18 #[derive(PartialEq, Eq, Debug, Clone, Copy)] 19 pub struct ThreadId { 20 /// Process ID (may or may not be present). 21 pub pid: Option<IdKind>, 22 /// Thread ID. 23 pub tid: IdKind, 24 } 25 26 impl TryFrom<&[u8]> for ThreadId { 27 type Error = (); 28 try_from(s: &[u8]) -> Result<Self, ()>29 fn try_from(s: &[u8]) -> Result<Self, ()> { 30 match s { 31 [b'p', s @ ..] => { 32 // p<pid>.<tid> 33 let mut s = s.split(|b| *b == b'.'); 34 let pid: IdKind = s.next().ok_or(())?.try_into()?; 35 let tid: IdKind = match s.next() { 36 Some(s) => s.try_into()?, 37 None => IdKind::All, // sending only p<pid> is valid 38 }; 39 40 Ok(ThreadId { 41 pid: Some(pid), 42 tid, 43 }) 44 } 45 _ => { 46 // <tid> 47 let tid: IdKind = s.try_into()?; 48 49 Ok(ThreadId { pid: None, tid }) 50 } 51 } 52 } 53 } 54 55 impl TryFrom<&[u8]> for IdKind { 56 type Error = (); 57 try_from(s: &[u8]) -> Result<Self, ()>58 fn try_from(s: &[u8]) -> Result<Self, ()> { 59 Ok(match s { 60 b"-1" => IdKind::All, 61 b"0" => IdKind::Any, 62 id => IdKind::WithID(NonZeroUsize::new(decode_hex(id).map_err(drop)?).ok_or(())?), 63 }) 64 } 65 } 66 67 impl TryFrom<&mut [u8]> for ThreadId { 68 type Error = (); 69 try_from(s: &mut [u8]) -> Result<Self, ()>70 fn try_from(s: &mut [u8]) -> Result<Self, ()> { 71 Self::try_from(s as &[u8]) 72 } 73 } 74 75 impl TryFrom<&mut [u8]> for IdKind { 76 type Error = (); 77 try_from(s: &mut [u8]) -> Result<Self, ()>78 fn try_from(s: &mut [u8]) -> Result<Self, ()> { 79 Self::try_from(s as &[u8]) 80 } 81 } 82