safe_libc/errno/
mod.rs

1//
2// Created:  Thu 16 Apr 2020 01:19:12 PM PDT
3// Modified: Wed 26 Nov 2025 03:02:25 PM PST
4//
5// Copyright (C) 2020 Robert Gill <rtgill82@gmail.com>
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to
9// deal in the Software without restriction, including without limitation the
10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11// sell copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in
15// all copies of the Software, its documentation and marketing & publicity
16// materials, and acknowledgment shall be given in the documentation, materials
17// and software packages that this Software was used.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25//
26
27use std::ffi::FromVecWithNulError;
28use std::ffi::NulError;
29use std::{cmp,fmt};
30use std::{error,result};
31
32mod source;
33use crate::errno::source::Source;
34use crate::string::strerror;
35
36#[cfg(target_family = "unix")]
37#[doc(inline)]
38pub use crate::posix::errno::*;
39
40#[cfg(target_family = "windows")]
41#[doc(inline)]
42pub use crate::windows::errno::*;
43
44pub type Result<T> = result::Result<T, Error>;
45
46pub struct Error {
47    errmsg: String,
48    errnum: i32,
49    source: Source
50}
51
52impl Error {
53    pub fn new(errnum: i32) -> Error {
54        let source = Source::None;
55        match strerror(errnum) {
56            Ok(errmsg) => Error { errmsg, errnum, source },
57            Err(err) => err
58        }
59    }
60
61    pub fn with_msg(errnum: i32, errmsg: String) -> Error {
62        let source = Source::None;
63        Error { errmsg, errnum, source }
64    }
65
66    pub fn errno() -> Error {
67        Error::new(errno())
68    }
69
70    #[cfg(target_family = "windows")]
71    pub fn doserrno() -> Error {
72        Error::new(doserrno())
73    }
74
75    pub fn msg(&self) -> &str {
76        &self.errmsg
77    }
78
79    pub fn num(&self) -> i32 {
80        self.errnum
81    }
82}
83
84impl error::Error for Error {
85    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
86        self.source.error_ref()
87    }
88}
89
90impl fmt::Debug for Error {
91    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        match &self.source {
93            Source::FromVecWithNulError(e) => <FromVecWithNulError as fmt::Debug>::fmt(e, f),
94            Source::NulError(e) => <NulError as fmt::Debug>::fmt(e, f),
95            Source::None => write!(f, "Error {{ errmsg: \"{}\", errnum: {} }}",
96                                       self.errmsg, self.errnum)
97        }
98    }
99}
100
101impl fmt::Display for Error {
102    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103        match &self.source {
104            Source::FromVecWithNulError(e) => write!(f, "Error: {}", e),
105            Source::NulError(e) => write!(f, "Error: {}", e),
106            Source::None => write!(f, "Error {}: {}", self.errnum, self.errmsg)
107        }
108    }
109}
110
111impl From<FromVecWithNulError> for Error {
112    fn from(value: FromVecWithNulError) -> Self {
113        Error {
114            errmsg: String::from("Interior NUL byte"),
115            errnum: 0,
116            source: Source::FromVecWithNulError(value)
117        }
118    }
119}
120
121impl From<NulError> for Error {
122    fn from(value: NulError) -> Self {
123        Error {
124            errmsg: String::from("Interior NUL byte"),
125            errnum: 0,
126            source: Source::NulError(value)
127        }
128    }
129}
130
131impl cmp::Eq for Error { }
132
133impl cmp::PartialEq for Error {
134    fn eq(&self, other: &Self) -> bool {
135        self.errnum == other.errnum
136    }
137}