cdns_rs/
error.rs

1/*-
2 * cdns-rs - a simple sync/async DNS query library
3 * 
4 * Copyright (C) 2020  Aleksandr Morozov
5 * 
6 * Copyright 2025 Aleksandr Morozov
7 * 
8 * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
9 * the European Commission - subsequent versions of the EUPL (the "Licence").
10 * 
11 * You may not use this work except in compliance with the Licence.
12 * 
13 * You may obtain a copy of the Licence at:
14 * 
15 *    https://joinup.ec.europa.eu/software/page/eupl
16 * 
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
20 * Licence for the specific language governing permissions and limitations
21 * under the Licence.
22 */
23
24use std::{str, fmt::{self, Write}};
25
26pub enum Writer
27{
28    None,
29    Wr(Vec<u8>)
30}
31
32unsafe impl Send for Writer {}
33impl Write for Writer
34{
35    fn write_str(&mut self, s: &str) -> fmt::Result 
36    {
37        match *self
38        {
39            Self::None => return Ok(()),
40            Self::Wr( ref mut buf ) =>
41            {
42                buf.extend(s.as_bytes());
43            }
44        }
45        
46        return Ok(());
47    }
48}
49
50impl Writer
51{
52    pub 
53    fn new() -> Self
54    {
55        #[cfg(not(feature = "no_error_output"))]
56        return Self::Wr( Vec::with_capacity(256) );
57
58        #[cfg(feature = "no_error_output")]
59        return Self::None;
60    }
61
62    pub 
63    fn is_some(&self) -> bool
64    {
65        match *self
66        {
67            Self::None => 
68                return false,
69            Self::Wr(ref k) => 
70                return k.len() > 0
71        }
72    }
73
74    pub unsafe
75    fn get_str(&self) -> &str
76    {
77        match *self
78        {
79            Self::Wr( ref buf ) =>
80            {
81                return str::from_utf8_unchecked( buf.as_slice() );
82            },
83            Self::None => return "",
84        }
85    }
86}
87
88
89#[cfg(not(feature = "no_error_output"))]
90#[macro_export]
91macro_rules! writer_error {
92    ($dst:expr, $($arg:tt)*) => (
93        { let _ = std::fmt::Write::write_fmt($dst, format_args!($($arg)*)); }
94    )
95}
96
97#[cfg(feature = "no_error_output")]
98#[macro_export]
99macro_rules! writer_error {
100    ($dst:expr, $($arg:tt)*) => ({})
101}
102
103
104pub(crate)
105fn map_read_err(e: std::io::Error) -> CDnsError
106{
107    return CDnsError::new(CDnsErrorType::IoError, format!("{}", e));
108}
109
110#[derive(Clone, PartialEq, Eq)]
111pub struct CDnsError
112{
113    pub err_code: CDnsErrorType,
114    pub message: String,
115}
116
117impl CDnsError
118{
119    pub fn new(err_code: CDnsErrorType, msg: String) -> Self
120    {
121        return CDnsError{err_code: err_code, message: msg};
122    }
123}
124
125impl fmt::Display for CDnsError 
126{
127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 
128    {
129        write!(f, "cdns: [{}], {}", self.err_code, self.message)
130    }
131}
132impl fmt::Debug for CDnsError 
133{
134    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 
135    {
136        write!(f, "cdns: [{}], {}", self.err_code, self.message)
137    }
138}
139
140#[derive(Clone, PartialEq, Eq)]
141pub enum CDnsErrorType
142{
143    /// Error related to DNS response parsing
144    DnsResponse,
145    /// Received response with unknown ID in header
146    RespIdMismatch,
147    /// Internal error (assertions...)
148    InternalError,
149    /// Socket, File error
150    IoError,
151    /// Response was truncated
152    MessageTruncated,
153    /// Timeout event
154    RequestTimeout,
155    /// Error in configuraion file (format)
156    ConfigError,
157    /// Nameservers unreachable
158    DnsNotAvailable,
159}
160
161impl fmt::Display for CDnsErrorType 
162{
163    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result 
164    {
165        match *self 
166        {
167            Self::DnsResponse => write!(f, "DNS response"),
168            Self::RespIdMismatch => write!(f, "Response ID mismatch"),
169            Self::InternalError => write!(f, "Internal Error"),
170            Self::IoError => write!(f, "IO Error"),
171            Self::MessageTruncated => write!(f, "Message was truncated"),
172            Self::RequestTimeout => write!(f, "Request receive timout"),
173            Self::ConfigError => write!(f, "Config file error"),
174            Self::DnsNotAvailable => write!(f, "DNS not available"),
175        }
176    }
177}
178
179pub type CDnsResult<T> = Result<T, CDnsError>;
180
181#[macro_export]
182macro_rules! internal_error 
183{
184    ($src:expr,$($arg:tt)*) => (
185        return std::result::Result::Err($crate::CDnsError::new($src, format!($($arg)*)))
186    )
187}
188
189#[macro_export]
190macro_rules! internal_error_map
191{
192    ($src:expr,$($arg:tt)*) => (
193        $crate::CDnsError::new($src, format!($($arg)*))
194    )
195}