1#[cfg(target_os = "macos")]
5mod sys_err {
6 #[cfg(not(feature = "std"))]
7 mod internal {
8 #[derive(Debug, thiserror::Error)]
9 #[error("system error")]
10 pub(crate) struct SysErr;
11
12 impl SysErr {
13 pub fn create() -> Self {
14 Self
15 }
16
17 pub fn create_anyhow() -> anyhow::Error {
18 anyhow::anyhow!(Self::create())
19 }
20 }
21 }
22
23 #[cfg(feature = "std")]
24 mod internal {
25 #[derive(Debug, thiserror::Error)]
26 #[error("system error: {0}")]
27 pub(crate) struct SysErr(std::io::Error);
28
29 impl SysErr {
30 pub fn create() -> Self {
31 Self(std::io::Error::last_os_error())
32 }
33
34 pub fn create_anyhow() -> anyhow::Error {
35 anyhow::anyhow!(Self::create())
36 }
37 }
38 }
39
40 pub(crate) use internal::SysErr;
41}
42
43#[cfg(target_os = "macos")]
44pub(crate) use sys_err::SysErr;
45
46pub(crate) mod private {
48 #[derive(Debug, Clone, thiserror::Error)]
51 #[error("allocation error, possibly OOM")]
52 pub(crate) struct AllocError(core::alloc::Layout);
53
54 impl AllocError {
55 #[must_use]
57 pub(crate) fn new(layout: core::alloc::Layout) -> Self {
58 Self(layout)
59 }
60 }
61
62 pub(crate) fn alloc_err_from_size_align(size: usize, align: usize) -> anyhow::Error {
63 let layout = core::alloc::Layout::from_size_align(size, align);
64 match layout {
65 Ok(layout) => anyhow::anyhow!(AllocError::new(layout)),
66 Err(layout_err) => anyhow::anyhow!(layout_err),
67 }
68 }
69
70 pub(crate) trait ResultExt {
71 type T;
72 fn map_anyhow(self) -> anyhow::Result<Self::T>;
73 }
74
75 impl<T, E: Send + Sync + core::fmt::Debug + core::fmt::Display + 'static> ResultExt
76 for core::result::Result<T, E>
77 {
78 type T = T;
79
80 fn map_anyhow(self) -> anyhow::Result<Self::T> {
81 self.map_err(|e| anyhow::anyhow!(e))
82 }
83 }
84}
85
86pub type Result = core::result::Result<(), Error>;
90
91#[must_use]
99#[derive(Debug, thiserror::Error)]
100pub enum Error {
101 #[error("{0}")]
104 BeingTraced(Traced),
105 #[error("{0}")]
108 Err(anyhow::Error),
109}
110
111#[derive(Debug, Clone)]
114pub struct Traced {
115 #[cfg(unix)]
116 pid: Option<rustix::process::Pid>,
117}
118
119#[cfg(unix)]
120impl Traced {
121 pub(crate) fn from_pid(pid: rustix::process::Pid) -> Self {
122 Self { pid: Some(pid) }
123 }
124}
125
126#[cfg(not(unix))]
127impl Traced {
128 pub(crate) const DEFAULT: Self = Self {};
129}
130
131impl core::fmt::Display for Traced {
132 #[cfg(unix)]
133 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
134 match self.pid {
135 Some(pid) => write!(
136 formatter,
137 "program is being traced by the process with pid {}",
138 pid.as_raw_nonzero()
139 ),
140 None => formatter.write_str("program is being traced"),
141 }
142 }
143
144 #[cfg(not(unix))]
145 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
146 formatter.write_str("program is being traced")
147 }
148}
149
150impl From<anyhow::Error> for Error {
151 fn from(err: anyhow::Error) -> Self {
152 Error::Err(err)
153 }
154}
155
156pub(crate) trait ResultExt {
157 fn create_ok() -> Self;
158 fn create_being_traced(traced: Traced) -> Self;
159 fn create_err(e: anyhow::Error) -> Self;
160}
161
162impl ResultExt for Result {
163 fn create_ok() -> Self {
164 Ok(())
165 }
166
167 fn create_being_traced(traced: Traced) -> Self {
168 Err(Error::BeingTraced(traced))
169 }
170
171 fn create_err(e: anyhow::Error) -> Self {
172 Err(Error::Err(e))
173 }
174}