blueprint-std 0.2.0-alpha.1

Re-exports of core/std for Tangle Blueprints
Documentation
#[cfg(feature = "std")]
pub use blueprint_std::io::{Error, ErrorKind, Result};

#[cfg(not(feature = "std"))]
pub use no_std::*;

#[cfg(not(feature = "std"))]
mod no_std {
    use crate::{boxed::Box, error, fmt};
    /// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
    /// associated traits.
    ///
    /// Errors mostly originate from the underlying OS, but custom instances of
    /// `Error` can be created with crafted error messages and a particular value of
    /// [`ErrorKind`].
    ///
    /// [`Read`]: crate::io::Read
    /// [`Write`]: crate::io::Write
    /// [`Seek`]: crate::io::Seek
    pub struct Error {
        repr: Repr,
    }

    pub type Result<T> = core::result::Result<T, Error>;

    impl fmt::Debug for Error {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            fmt::Debug::fmt(&self.repr, f)
        }
    }

    enum Repr {
        Simple(ErrorKind),
        Custom(Box<Custom>),
    }

    #[derive(Debug)]
    struct Custom {
        kind: ErrorKind,
        error: Box<dyn error::Error + Send + Sync>,
    }

    /// A list specifying general categories of I/O error.
    ///
    /// This list is intended to grow over time and it is not recommended to
    /// exhaustively match against it.
    ///
    /// It is used with the [`io::Error`] type.
    ///
    /// [`io::Error`]: Error
    #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    #[allow(deprecated)]
    #[non_exhaustive]
    pub enum ErrorKind {
        /// An entity was not found, often a file.
        NotFound,
        /// The operation lacked the necessary privileges to complete.
        PermissionDenied,
        /// The connection was refused by the remote server.
        ConnectionRefused,
        /// The connection was reset by the remote server.
        ConnectionReset,
        /// The connection was aborted (terminated) by the remote server.
        ConnectionAborted,
        /// The network operation failed because it was not connected yet.
        NotConnected,
        /// A socket address could not be bound because the address is already in
        /// use elsewhere.
        AddrInUse,
        /// A nonexistent interface was requested or the requested address was not
        /// local.
        AddrNotAvailable,
        /// The operation failed because a pipe was closed.
        BrokenPipe,
        /// An entity already exists, often a file.
        AlreadyExists,
        /// The operation needs to block to complete, but the blocking operation was
        /// requested to not occur.
        WouldBlock,
        /// A parameter was incorrect.
        InvalidInput,
        /// Data not valid for the operation were encountered.
        ///
        /// Unlike [`InvalidInput`], this typically means that the operation
        /// parameters were valid, however the error was caused by malformed
        /// input data.
        ///
        /// For example, a function that reads a file into a string will error with
        /// `InvalidData` if the file's contents are not valid UTF-8.
        ///
        /// [`InvalidInput`]: ErrorKind::InvalidInput
        InvalidData,
        /// The I/O operation's timeout expired, causing it to be canceled.
        TimedOut,
        /// An error returned when an operation could not be completed because a
        /// call to [`write`] returned [`Ok(0)`].
        ///
        /// This typically means that an operation could only succeed if it wrote a
        /// particular number of bytes but only a smaller number of bytes could be
        /// written.
        ///
        /// [`write`]: crate::io::Write::write
        /// [`Ok(0)`]: Ok
        WriteZero,
        /// This operation was interrupted.
        ///
        /// Interrupted operations can typically be retried.
        Interrupted,
        /// Any I/O error not part of this list.
        ///
        /// Errors that are `Other` now may move to a different or a new
        /// [`ErrorKind`] variant in the future. It is not recommended to match
        /// an error against `Other` and to expect any additional characteristics,
        /// e.g., a specific [`Error::raw_os_error`] return value.
        Other,

        /// An error returned when an operation could not be completed because an
        /// "end of file" was reached prematurely.
        ///
        /// This typically means that an operation could only succeed if it read a
        /// particular number of bytes but only a smaller number of bytes could be
        /// read.
        UnexpectedEof,
    }

    impl ErrorKind {
        pub(crate) fn as_str(self) -> &'static str {
            match self {
                ErrorKind::NotFound => "entity not found",
                ErrorKind::PermissionDenied => "permission denied",
                ErrorKind::ConnectionRefused => "connection refused",
                ErrorKind::ConnectionReset => "connection reset",
                ErrorKind::ConnectionAborted => "connection aborted",
                ErrorKind::NotConnected => "not connected",
                ErrorKind::AddrInUse => "address in use",
                ErrorKind::AddrNotAvailable => "address not available",
                ErrorKind::BrokenPipe => "broken pipe",
                ErrorKind::AlreadyExists => "entity already exists",
                ErrorKind::WouldBlock => "operation would block",
                ErrorKind::InvalidInput => "invalid input parameter",
                ErrorKind::InvalidData => "invalid data",
                ErrorKind::TimedOut => "timed out",
                ErrorKind::WriteZero => "write zero",
                ErrorKind::Interrupted => "operation interrupted",
                ErrorKind::Other => "other os error",
                ErrorKind::UnexpectedEof => "unexpected end of file",
            }
        }
    }

    /// Intended for use for errors not exposed to the user, where allocating onto
    /// the heap (for normal construction via `Error::new`) is too costly.
    impl From<ErrorKind> for Error {
        /// Converts an [`ErrorKind`] into an [`Error`].
        ///
        /// This conversion allocates a new error with a simple representation of error kind.
        ///
        /// # Examples
        ///
        /// ```
        /// use blueprint_std::io::{Error, ErrorKind};
        ///
        /// let not_found = ErrorKind::NotFound;
        /// let error = Error::from(not_found);
        /// assert_eq!("entity not found", format!("{}", error));
        /// ```
        #[inline]
        fn from(kind: ErrorKind) -> Error {
            Error {
                repr: Repr::Simple(kind),
            }
        }
    }

    impl Error {
        /// Creates a new I/O error from a known kind of error as well as an
        /// arbitrary error payload.
        ///
        /// This function is used to generically create I/O errors which do not
        /// originate from the OS itself. The `error` argument is an arbitrary
        /// payload which will be contained in this [`Error`].
        ///
        /// # Examples
        ///
        /// ```
        /// use blueprint_std::io::{Error, ErrorKind};
        ///
        /// // errors can be created from strings
        /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
        ///
        /// // errors can also be created from other errors
        /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
        /// ```
        pub fn new<E>(kind: ErrorKind, error: E) -> Error
        where
            E: Into<Box<dyn error::Error + Send + Sync>>,
        {
            Self::_new(kind, error.into())
        }

        fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
            Error {
                repr: Repr::Custom(Box::new(Custom { kind, error })),
            }
        }

        #[must_use]
        pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
            match self.repr {
                Repr::Simple(..) => None,
                Repr::Custom(ref c) => Some(&*c.error),
            }
        }

        pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
            match self.repr {
                Repr::Simple(..) => None,
                Repr::Custom(ref mut c) => Some(&mut *c.error),
            }
        }

        /// Consumes the `Error`, returning its inner error (if any).
        ///
        /// If this [`Error`] was constructed via [`new`] then this function will
        /// return [`Some`], otherwise it will return [`None`].
        ///
        /// [`new`]: Error::new
        #[must_use]
        pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
            match self.repr {
                Repr::Simple(..) => None,
                Repr::Custom(c) => Some(c.error),
            }
        }

        /// Returns the corresponding [`ErrorKind`] for this error.
        #[must_use]
        pub fn kind(&self) -> ErrorKind {
            match self.repr {
                Repr::Custom(ref c) => c.kind,
                Repr::Simple(kind) => kind,
            }
        }
    }

    impl fmt::Debug for Repr {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            match *self {
                Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
                Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
            }
        }
    }

    impl fmt::Display for Error {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            match self.repr {
                Repr::Custom(ref c) => c.error.fmt(fmt),
                Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
            }
        }
    }

    impl error::Error for Error {
        fn source(&self) -> Option<&(dyn error::Error + 'static)> {
            match self.repr {
                Repr::Simple(..) => None,
                Repr::Custom(ref c) => c.error.source(),
            }
        }
    }

    #[allow(dead_code)]
    fn assert_error_is_sync_send() {
        fn is_sync_send<T: Sync + Send>() {}
        is_sync_send::<Error>();
    }
}