use crate::protocol::common::hex::decode_hex;
use core::convert::TryFrom;
use core::convert::TryInto;
use core::num::NonZeroUsize;
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum IdKind {
All,
Any,
WithId(NonZeroUsize),
}
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub struct ThreadId {
pub pid: Option<IdKind>,
pub tid: IdKind,
}
impl TryFrom<&[u8]> for ThreadId {
type Error = ();
fn try_from(s: &[u8]) -> Result<Self, ()> {
match s {
[b'p', s @ ..] => {
let mut s = s.split(|b| *b == b'.');
let pid: IdKind = s.next().ok_or(())?.try_into()?;
let tid: IdKind = match s.next() {
Some(s) => s.try_into()?,
None => IdKind::All, };
Ok(ThreadId {
pid: Some(pid),
tid,
})
}
_ => {
let tid: IdKind = s.try_into()?;
Ok(ThreadId { pid: None, tid })
}
}
}
}
impl TryFrom<&[u8]> for IdKind {
type Error = ();
fn try_from(s: &[u8]) -> Result<Self, ()> {
Ok(match s {
b"-1" => IdKind::All,
b"0" => IdKind::Any,
id => IdKind::WithId(NonZeroUsize::new(decode_hex(id).map_err(drop)?).ok_or(())?),
})
}
}
impl TryFrom<&mut [u8]> for ThreadId {
type Error = ();
fn try_from(s: &mut [u8]) -> Result<Self, ()> {
Self::try_from(s as &[u8])
}
}
impl TryFrom<&mut [u8]> for IdKind {
type Error = ();
fn try_from(s: &mut [u8]) -> Result<Self, ()> {
Self::try_from(s as &[u8])
}
}
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum SpecificIdKind {
WithId(core::num::NonZeroUsize),
All,
}
#[derive(Debug, Copy, Clone)]
pub struct SpecificThreadId {
pub pid: Option<SpecificIdKind>,
pub tid: SpecificIdKind,
}
impl TryFrom<IdKind> for SpecificIdKind {
type Error = ();
fn try_from(id: IdKind) -> Result<SpecificIdKind, ()> {
Ok(match id {
IdKind::All => SpecificIdKind::All,
IdKind::WithId(id) => SpecificIdKind::WithId(id),
IdKind::Any => return Err(()),
})
}
}
impl TryFrom<ThreadId> for SpecificThreadId {
type Error = ();
fn try_from(thread: ThreadId) -> Result<SpecificThreadId, ()> {
Ok(SpecificThreadId {
pid: match thread.pid {
None => None,
Some(id_kind) => Some(id_kind.try_into()?),
},
tid: thread.tid.try_into()?,
})
}
}
#[derive(Debug, Copy, Clone)]
pub struct ConcreteThreadId {
pub pid: Option<NonZeroUsize>,
pub tid: NonZeroUsize,
}
impl TryFrom<ThreadId> for ConcreteThreadId {
type Error = ();
fn try_from(thread: ThreadId) -> Result<ConcreteThreadId, ()> {
Ok(ConcreteThreadId {
pid: match thread.pid {
None => None,
Some(id_kind) => Some(id_kind.try_into()?),
},
tid: thread.tid.try_into()?,
})
}
}
impl TryFrom<IdKind> for NonZeroUsize {
type Error = ();
fn try_from(value: IdKind) -> Result<NonZeroUsize, ()> {
match value {
IdKind::WithId(v) => Ok(v),
_ => Err(()),
}
}
}