#[cfg(test)]
mod tests;
#[cfg(target_pointer_width = "64")]
mod repr_bitpacked;
#[cfg(target_pointer_width = "64")]
use repr_bitpacked::Repr;
#[cfg(not(target_pointer_width = "64"))]
mod repr_unpacked;
#[cfg(not(target_pointer_width = "64"))]
use repr_unpacked::Repr;
use crate::error;
use crate::fmt;
use crate::result;
use crate::sys;
#[stable(feature = "rust1", since = "1.0.0")]
pub type Result<T> = result::Result<T, Error>;
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Error {
repr: Repr,
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.repr, f)
}
}
#[cfg_attr(test, derive(Debug))]
enum ErrorData<C> {
Os(RawOsError),
Simple(ErrorKind),
SimpleMessage(&'static SimpleMessage),
Custom(C),
}
#[unstable(feature = "raw_os_error_ty", issue = "107792")]
pub type RawOsError = i32;
#[repr(align(4))]
#[derive(Debug)]
pub(crate) struct SimpleMessage {
kind: ErrorKind,
message: &'static str,
}
impl SimpleMessage {
pub(crate) const fn new(kind: ErrorKind, message: &'static str) -> Self {
Self { kind, message }
}
}
pub(crate) macro const_io_error($kind:expr, $message:expr $(,)?) {
$crate::io::error::Error::from_static_message({
const MESSAGE_DATA: $crate::io::error::SimpleMessage =
$crate::io::error::SimpleMessage::new($kind, $message);
&MESSAGE_DATA
})
}
#[derive(Debug)]
#[repr(align(4))]
struct Custom {
kind: ErrorKind,
error: Box<dyn error::Error + Send + Sync>,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
#[non_exhaustive]
pub enum ErrorKind {
#[stable(feature = "rust1", since = "1.0.0")]
NotFound,
#[stable(feature = "rust1", since = "1.0.0")]
PermissionDenied,
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionRefused,
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionReset,
#[unstable(feature = "io_error_more", issue = "86442")]
HostUnreachable,
#[unstable(feature = "io_error_more", issue = "86442")]
NetworkUnreachable,
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionAborted,
#[stable(feature = "rust1", since = "1.0.0")]
NotConnected,
#[stable(feature = "rust1", since = "1.0.0")]
AddrInUse,
#[stable(feature = "rust1", since = "1.0.0")]
AddrNotAvailable,
#[unstable(feature = "io_error_more", issue = "86442")]
NetworkDown,
#[stable(feature = "rust1", since = "1.0.0")]
BrokenPipe,
#[stable(feature = "rust1", since = "1.0.0")]
AlreadyExists,
#[stable(feature = "rust1", since = "1.0.0")]
WouldBlock,
#[unstable(feature = "io_error_more", issue = "86442")]
NotADirectory,
#[unstable(feature = "io_error_more", issue = "86442")]
IsADirectory,
#[unstable(feature = "io_error_more", issue = "86442")]
DirectoryNotEmpty,
#[unstable(feature = "io_error_more", issue = "86442")]
ReadOnlyFilesystem,
#[unstable(feature = "io_error_more", issue = "86442")]
FilesystemLoop,
#[unstable(feature = "io_error_more", issue = "86442")]
StaleNetworkFileHandle,
#[stable(feature = "rust1", since = "1.0.0")]
InvalidInput,
#[stable(feature = "io_invalid_data", since = "1.2.0")]
InvalidData,
#[stable(feature = "rust1", since = "1.0.0")]
TimedOut,
#[stable(feature = "rust1", since = "1.0.0")]
WriteZero,
#[unstable(feature = "io_error_more", issue = "86442")]
StorageFull,
#[unstable(feature = "io_error_more", issue = "86442")]
NotSeekable,
#[unstable(feature = "io_error_more", issue = "86442")]
FilesystemQuotaExceeded,
#[unstable(feature = "io_error_more", issue = "86442")]
FileTooLarge,
#[unstable(feature = "io_error_more", issue = "86442")]
ResourceBusy,
#[unstable(feature = "io_error_more", issue = "86442")]
ExecutableFileBusy,
#[unstable(feature = "io_error_more", issue = "86442")]
Deadlock,
#[unstable(feature = "io_error_more", issue = "86442")]
CrossesDevices,
#[unstable(feature = "io_error_more", issue = "86442")]
TooManyLinks,
#[unstable(feature = "io_error_more", issue = "86442")]
InvalidFilename,
#[unstable(feature = "io_error_more", issue = "86442")]
ArgumentListTooLong,
#[stable(feature = "rust1", since = "1.0.0")]
Interrupted,
#[stable(feature = "unsupported_error", since = "1.53.0")]
Unsupported,
#[stable(feature = "read_exact", since = "1.6.0")]
UnexpectedEof,
#[stable(feature = "out_of_memory_error", since = "1.54.0")]
OutOfMemory,
#[stable(feature = "rust1", since = "1.0.0")]
Other,
#[unstable(feature = "io_error_uncategorized", issue = "none")]
#[doc(hidden)]
Uncategorized,
}
impl ErrorKind {
pub(crate) fn as_str(&self) -> &'static str {
use ErrorKind::*;
match *self {
AddrInUse => "address in use",
AddrNotAvailable => "address not available",
AlreadyExists => "entity already exists",
ArgumentListTooLong => "argument list too long",
BrokenPipe => "broken pipe",
ConnectionAborted => "connection aborted",
ConnectionRefused => "connection refused",
ConnectionReset => "connection reset",
CrossesDevices => "cross-device link or rename",
Deadlock => "deadlock",
DirectoryNotEmpty => "directory not empty",
ExecutableFileBusy => "executable file busy",
FileTooLarge => "file too large",
FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
FilesystemQuotaExceeded => "filesystem quota exceeded",
HostUnreachable => "host unreachable",
Interrupted => "operation interrupted",
InvalidData => "invalid data",
InvalidFilename => "invalid filename",
InvalidInput => "invalid input parameter",
IsADirectory => "is a directory",
NetworkDown => "network down",
NetworkUnreachable => "network unreachable",
NotADirectory => "not a directory",
NotConnected => "not connected",
NotFound => "entity not found",
NotSeekable => "seek on unseekable file",
Other => "other error",
OutOfMemory => "out of memory",
PermissionDenied => "permission denied",
ReadOnlyFilesystem => "read-only filesystem or storage medium",
ResourceBusy => "resource busy",
StaleNetworkFileHandle => "stale network file handle",
StorageFull => "no storage space",
TimedOut => "timed out",
TooManyLinks => "too many links",
Uncategorized => "uncategorized error",
UnexpectedEof => "unexpected end of file",
Unsupported => "unsupported",
WouldBlock => "operation would block",
WriteZero => "write zero",
}
}
}
#[stable(feature = "io_errorkind_display", since = "1.60.0")]
impl fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str(self.as_str())
}
}
#[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
impl From<ErrorKind> for Error {
#[inline]
fn from(kind: ErrorKind) -> Error {
Error { repr: Repr::new_simple(kind) }
}
}
impl Error {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where
E: Into<Box<dyn error::Error + Send + Sync>>,
{
Self::_new(kind, error.into())
}
#[unstable(feature = "io_error_other", issue = "91946")]
pub fn other<E>(error: E) -> Error
where
E: Into<Box<dyn error::Error + Send + Sync>>,
{
Self::_new(ErrorKind::Other, error.into())
}
fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
Error { repr: Repr::new_custom(Box::new(Custom { kind, error })) }
}
#[inline]
pub(crate) const fn from_static_message(msg: &'static SimpleMessage) -> Error {
Self { repr: Repr::new_simple_message(msg) }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "GetLastError")]
#[doc(alias = "errno")]
#[must_use]
#[inline]
pub fn last_os_error() -> Error {
Error::from_raw_os_error(sys::os::errno())
}
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
pub fn from_raw_os_error(code: RawOsError) -> Error {
Error { repr: Repr::new_os(code) }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
pub fn raw_os_error(&self) -> Option<RawOsError> {
match self.repr.data() {
ErrorData::Os(i) => Some(i),
ErrorData::Custom(..) => None,
ErrorData::Simple(..) => None,
ErrorData::SimpleMessage(..) => None,
}
}
#[stable(feature = "io_error_inner", since = "1.3.0")]
#[must_use]
#[inline]
pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
match self.repr.data() {
ErrorData::Os(..) => None,
ErrorData::Simple(..) => None,
ErrorData::SimpleMessage(..) => None,
ErrorData::Custom(c) => Some(&*c.error),
}
}
#[stable(feature = "io_error_inner", since = "1.3.0")]
#[must_use]
#[inline]
pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
match self.repr.data_mut() {
ErrorData::Os(..) => None,
ErrorData::Simple(..) => None,
ErrorData::SimpleMessage(..) => None,
ErrorData::Custom(c) => Some(&mut *c.error),
}
}
#[stable(feature = "io_error_inner", since = "1.3.0")]
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
match self.repr.into_data() {
ErrorData::Os(..) => None,
ErrorData::Simple(..) => None,
ErrorData::SimpleMessage(..) => None,
ErrorData::Custom(c) => Some(c.error),
}
}
#[unstable(feature = "io_error_downcast", issue = "99262")]
pub fn downcast<E>(self) -> result::Result<Box<E>, Self>
where
E: error::Error + Send + Sync + 'static,
{
match self.repr.into_data() {
ErrorData::Custom(b) if b.error.is::<E>() => {
let res = (*b).error.downcast::<E>();
Ok(res.unwrap())
}
repr_data => Err(Self { repr: Repr::new(repr_data) }),
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
pub fn kind(&self) -> ErrorKind {
match self.repr.data() {
ErrorData::Os(code) => sys::decode_error_kind(code),
ErrorData::Custom(c) => c.kind,
ErrorData::Simple(kind) => kind,
ErrorData::SimpleMessage(m) => m.kind,
}
}
}
impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.data() {
ErrorData::Os(code) => fmt
.debug_struct("Os")
.field("code", &code)
.field("kind", &sys::decode_error_kind(code))
.field("message", &sys::os::error_string(code))
.finish(),
ErrorData::Custom(c) => fmt::Debug::fmt(&c, fmt),
ErrorData::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
ErrorData::SimpleMessage(msg) => fmt
.debug_struct("Error")
.field("kind", &msg.kind)
.field("message", &msg.message)
.finish(),
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.repr.data() {
ErrorData::Os(code) => {
let detail = sys::os::error_string(code);
write!(fmt, "{detail} (os error {code})")
}
ErrorData::Custom(ref c) => c.error.fmt(fmt),
ErrorData::Simple(kind) => write!(fmt, "{}", kind.as_str()),
ErrorData::SimpleMessage(msg) => msg.message.fmt(fmt),
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl error::Error for Error {
#[allow(deprecated, deprecated_in_future)]
fn description(&self) -> &str {
match self.repr.data() {
ErrorData::Os(..) | ErrorData::Simple(..) => self.kind().as_str(),
ErrorData::SimpleMessage(msg) => msg.message,
ErrorData::Custom(c) => c.error.description(),
}
}
#[allow(deprecated)]
fn cause(&self) -> Option<&dyn error::Error> {
match self.repr.data() {
ErrorData::Os(..) => None,
ErrorData::Simple(..) => None,
ErrorData::SimpleMessage(..) => None,
ErrorData::Custom(c) => c.error.cause(),
}
}
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self.repr.data() {
ErrorData::Os(..) => None,
ErrorData::Simple(..) => None,
ErrorData::SimpleMessage(..) => None,
ErrorData::Custom(c) => c.error.source(),
}
}
}
fn _assert_error_is_sync_send() {
fn _is_sync_send<T: Sync + Send>() {}
_is_sync_send::<Error>();
}