1use derive_more::{Display, IsVariant, TryUnwrap, Unwrap};
10
11use crate::{name::LabelTooLongDetail, wire::*};
12cfg_heap! {
16 use crate::{Name, QueryHandle, ServiceHandle};
17}
18
19#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display, thiserror::Error)]
21#[display("buffer too short: needed {needed} bytes at offset {at}, had {have}")]
22pub struct BufferTooShortDetail {
23 needed: usize,
24 at: usize,
25 have: usize,
26}
27
28impl BufferTooShortDetail {
29 #[inline(always)]
31 pub const fn new(needed: usize, at: usize, have: usize) -> Self {
32 Self { needed, at, have }
33 }
34
35 #[inline(always)]
37 pub const fn needed(&self) -> usize {
38 self.needed
39 }
40
41 #[inline(always)]
43 pub const fn at(&self) -> usize {
44 self.at
45 }
46
47 #[inline(always)]
49 pub const fn have(&self) -> usize {
50 self.have
51 }
52
53 #[inline(always)]
57 pub const fn is_empty(&self) -> bool {
58 self.have == 0
59 }
60}
61
62#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display, thiserror::Error)]
64#[display("output buffer too small: needed {needed} bytes, have {have}")]
65pub struct BufferTooSmallDetail {
66 needed: usize,
67 have: usize,
68}
69
70impl BufferTooSmallDetail {
71 #[inline(always)]
73 pub const fn new(needed: usize, have: usize) -> Self {
74 Self { needed, have }
75 }
76
77 #[inline(always)]
79 pub const fn needed(&self) -> usize {
80 self.needed
81 }
82
83 #[inline(always)]
85 pub const fn have(&self) -> usize {
86 self.have
87 }
88
89 #[inline(always)]
93 pub const fn is_empty(&self) -> bool {
94 self.have == 0
95 }
96}
97
98#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display, thiserror::Error)]
100#[display("compression pointer points forward: ptr {ptr} > current {at}")]
101pub struct PointerForwardDetail {
102 ptr: u16,
103 at: u16,
104}
105
106impl PointerForwardDetail {
107 #[inline(always)]
109 pub const fn new(ptr: u16, at: u16) -> Self {
110 Self { ptr, at }
111 }
112
113 #[inline(always)]
115 pub const fn ptr(&self) -> u16 {
116 self.ptr
117 }
118
119 #[inline(always)]
121 pub const fn at(&self) -> u16 {
122 self.at
123 }
124}
125
126#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Display, thiserror::Error)]
128#[display("rdlength {rdlen} at offset {at} exceeds remaining {rem} bytes")]
129pub struct RdlengthOverrunDetail {
130 rdlen: u16,
131 at: usize,
132 rem: usize,
133}
134
135impl RdlengthOverrunDetail {
136 #[inline(always)]
138 pub const fn new(rdlen: u16, at: usize, rem: usize) -> Self {
139 Self { rdlen, at, rem }
140 }
141
142 #[inline(always)]
144 pub const fn rdlen(&self) -> u16 {
145 self.rdlen
146 }
147
148 #[inline(always)]
150 pub const fn at(&self) -> usize {
151 self.at
152 }
153
154 #[inline(always)]
156 pub const fn rem(&self) -> usize {
157 self.rem
158 }
159}
160
161#[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
163#[unwrap(ref)]
164#[try_unwrap(ref)]
165#[non_exhaustive]
166pub enum ParseError {
167 #[error(transparent)]
169 BufferTooShort(BufferTooShortDetail),
170
171 #[error(transparent)]
173 LabelTooLong(LabelTooLongDetail),
174
175 #[error("name exceeds max length {0} bytes")]
177 NameTooLong(usize),
178
179 #[error("name compression pointer cycle detected")]
181 PointerCycle,
182
183 #[error("name compression pointer chain exceeded {0} hops")]
185 PointerChainTooLong(u8),
186
187 #[error(transparent)]
189 PointerForward(PointerForwardDetail),
190
191 #[error("unknown label kind in byte {0:#010b}")]
193 InvalidLabelKind(u8),
194
195 #[error(transparent)]
197 RdlengthOverrun(RdlengthOverrunDetail),
198
199 #[error(transparent)]
201 IntegerConversion(#[from] core::num::TryFromIntError),
202
203 #[error("unsupported name-bearing record type {0}")]
209 UnsupportedNameBearingType(u16),
210}
211
212#[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
214#[unwrap(ref)]
215#[try_unwrap(ref)]
216#[non_exhaustive]
217pub enum EncodeError {
218 #[error(transparent)]
220 BufferTooSmall(BufferTooSmallDetail),
221
222 #[error(transparent)]
224 IntegerConversion(#[from] core::num::TryFromIntError),
225}
226
227#[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
229#[unwrap(ref)]
230#[try_unwrap(ref)]
231#[non_exhaustive]
232pub enum HandleTimeoutError {
233 #[error("deadline arithmetic overflow")]
235 Overflow,
236}
237
238#[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
240#[unwrap(ref)]
241#[try_unwrap(ref)]
242#[non_exhaustive]
243pub enum TransmitError {
244 #[error(transparent)]
246 BufferTooSmall(BufferTooSmallDetail),
247}
248
249#[derive(Debug, Clone, Eq, PartialEq, thiserror::Error)]
251#[non_exhaustive]
252#[error("pool capacity exceeded")]
253pub struct StorageFullError;
254
255#[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
257#[unwrap(ref)]
258#[try_unwrap(ref)]
259#[non_exhaustive]
260pub enum HandleError {
261 #[error(transparent)]
263 Parse(#[from] ParseError),
264
265 #[error("incoming opcode `{0}` is not Query")]
267 InvalidOpcode(Opcode),
268
269 #[error("incoming response code `{0}` is not NoError")]
271 InvalidResponseCode(ResponseCode),
272}
273
274cfg_heap! {
275 #[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
277 #[unwrap(ref)]
278 #[try_unwrap(ref)]
279 #[non_exhaustive]
280 pub enum RegisterServiceError {
281 #[error("service `{0}` already registered")]
283 NameAlreadyRegistered(crate::Name),
284
285 #[error(transparent)]
287 StorageFull(#[from] StorageFullError),
288 }
289}
290
291#[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
293#[unwrap(ref)]
294#[try_unwrap(ref)]
295#[non_exhaustive]
296pub enum StartQueryError {
297 #[error(transparent)]
299 StorageFull(#[from] StorageFullError),
300}
301
302cfg_heap! {
303 #[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
306 #[unwrap(ref)]
307 #[try_unwrap(ref)]
308 #[non_exhaustive]
309 pub enum HandleServiceRenamedError {
310 #[error("name `{0}` is already registered to a different service")]
312 NameAlreadyRegistered(Name),
313
314 #[error("service handle {0} not found")]
316 ServiceNotFound(ServiceHandle),
317 }
318
319 #[derive(Debug, Clone, IsVariant, Unwrap, TryUnwrap, thiserror::Error)]
325 #[unwrap(ref)]
326 #[try_unwrap(ref)]
327 #[non_exhaustive]
328 pub enum CancelQueryError {
329 #[error("query handle {0} not found")]
331 QueryNotFound(QueryHandle),
332 }
333}
334
335#[cfg(test)]
336#[allow(clippy::unwrap_used)]
337mod tests;