nu_protocol/errors/shell_error/
network.rs

1use miette::{Diagnostic, LabeledSpan};
2use thiserror::Error;
3
4use crate::{ShellError, Span, Spanned};
5
6#[derive(Debug, Clone, PartialEq, Error, Diagnostic)]
7pub enum NetworkError {
8    // Replace ShellError::NetworkFailure with this one
9    #[error("Network failure")]
10    #[diagnostic(code(nu::shell::network))]
11    Generic {
12        msg: String,
13        #[label("{msg}")]
14        span: Span,
15    },
16
17    #[error(transparent)]
18    #[diagnostic(transparent)]
19    Dns(DnsError),
20    // TODO: add more precise network errors to avoid generic ones
21}
22
23#[derive(Debug, Clone, PartialEq, Error)]
24#[error("DNS Error")]
25pub struct DnsError {
26    pub kind: DnsErrorKind,
27    pub span: Span,
28    pub query: Spanned<String>,
29}
30
31impl Diagnostic for DnsError {
32    fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
33        self.kind.code()
34    }
35
36    fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
37        Some(Box::new(
38            [
39                LabeledSpan::new_with_span(Some("Could not be resolved".into()), self.query.span),
40                LabeledSpan::new_with_span(Some(self.kind.to_string()), self.span),
41            ]
42            .into_iter(),
43        ))
44    }
45
46    fn help<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
47        Some(Box::new(format!("While querying \"{}\"", self.query)))
48    }
49}
50
51#[derive(Debug, Clone, PartialEq, Error, Diagnostic)]
52pub enum DnsErrorKind {
53    /// Temporary failure in name resolution.
54    ///
55    /// May also be returned when the DNS server returns SERVFAIL.
56    #[error("Temporary failure in name resolution")]
57    #[diagnostic(code(nu::shell::network::dns::again))]
58    Again,
59
60    /// NAME or SERVICE is unknown.
61    ///
62    /// May also be returned when the domain does not exist (NXDOMAIN) or
63    /// exists but has no address records (NODATA).
64    #[error("Name or service is unknown")]
65    #[diagnostic(code(nu::shell::network::dns::no_name))]
66    NoName,
67
68    /// The specified network host exists, but has no data defined.
69    ///
70    /// This is no longer a POSIX standard, however it is still returned by
71    /// some platforms.
72    #[error("Host exists but has no address records")]
73    #[diagnostic(code(nu::shell::network::dns::no_data))]
74    NoData,
75
76    /// Non recoverable failure in name resolution.
77    #[error("Non recoverable failure in name resolution")]
78    #[diagnostic(code(nu::shell::network::dns::fail))]
79    Fail,
80}
81
82impl From<DnsError> for ShellError {
83    fn from(value: DnsError) -> Self {
84        ShellError::Network(NetworkError::Dns(value))
85    }
86}