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