aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/error.rs
diff options
context:
space:
mode:
authorFenrir <[email protected]>2017-01-19 01:30:05 -0700
committerFenrir <[email protected]>2017-01-21 17:44:58 -0700
commit08b71a18cd917724ee3d270d49a78e508a176e36 (patch)
treeb5eb42603929957f4bc826942e29b154c863003a /ctr-std/src/error.rs
parentUpdate Cargo.toml (diff)
downloadctru-rs-08b71a18cd917724ee3d270d49a78e508a176e36.tar.xz
ctru-rs-08b71a18cd917724ee3d270d49a78e508a176e36.zip
We stdlib now
Diffstat (limited to 'ctr-std/src/error.rs')
-rw-r--r--ctr-std/src/error.rs497
1 files changed, 497 insertions, 0 deletions
diff --git a/ctr-std/src/error.rs b/ctr-std/src/error.rs
new file mode 100644
index 0000000..454fa47
--- /dev/null
+++ b/ctr-std/src/error.rs
@@ -0,0 +1,497 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Traits for working with Errors.
+//!
+//! # The `Error` trait
+//!
+//! `Error` is a trait representing the basic expectations for error values,
+//! i.e. values of type `E` in [`Result<T, E>`]. At a minimum, errors must provide
+//! a description, but they may optionally provide additional detail (via
+//! [`Display`]) and cause chain information:
+//!
+//! ```
+//! use std::fmt::Display;
+//!
+//! trait Error: Display {
+//! fn description(&self) -> &str;
+//!
+//! fn cause(&self) -> Option<&Error> { None }
+//! }
+//! ```
+//!
+//! The [`cause`] method is generally used when errors cross "abstraction
+//! boundaries", i.e. when a one module must report an error that is "caused"
+//! by an error from a lower-level module. This setup makes it possible for the
+//! high-level module to provide its own errors that do not commit to any
+//! particular implementation, but also reveal some of its implementation for
+//! debugging via [`cause`] chains.
+//!
+//! [`Result<T, E>`]: ../result/enum.Result.html
+//! [`Display`]: ../fmt/trait.Display.html
+//! [`cause`]: trait.Error.html#method.cause
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// A note about crates and the facade:
+//
+// Originally, the `Error` trait was defined in libcore, and the impls
+// were scattered about. However, coherence objected to this
+// arrangement, because to create the blanket impls for `Box` required
+// knowing that `&str: !Error`, and we have no means to deal with that
+// sort of conflict just now. Therefore, for the time being, we have
+// moved the `Error` trait into libstd. As we evolve a sol'n to the
+// coherence challenge (e.g., specialization, neg impls, etc) we can
+// reconsider what crate these items belong in.
+
+use any::TypeId;
+use cell;
+use char;
+use fmt::{self, Debug, Display};
+use mem::transmute;
+use num;
+use str;
+use string;
+
+/// Base functionality for all errors in Rust.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait Error: Debug + Display {
+ /// A short description of the error.
+ ///
+ /// The description should only be used for a simple message.
+ /// It should not contain newlines or sentence-ending punctuation,
+ /// to facilitate embedding in larger user-facing strings.
+ /// For showing formatted error messages with more information see
+ /// [`Display`].
+ ///
+ /// [`Display`]: ../fmt/trait.Display.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::error::Error;
+ ///
+ /// match "xc".parse::<u32>() {
+ /// Err(e) => {
+ /// println!("Error: {}", e.description());
+ /// }
+ /// _ => println!("No error"),
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn description(&self) -> &str;
+
+ /// The lower-level cause of this error, if any.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::error::Error;
+ /// use std::fmt;
+ ///
+ /// #[derive(Debug)]
+ /// struct SuperError {
+ /// side: SuperErrorSideKick,
+ /// }
+ ///
+ /// impl fmt::Display for SuperError {
+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ /// write!(f, "SuperError is here!")
+ /// }
+ /// }
+ ///
+ /// impl Error for SuperError {
+ /// fn description(&self) -> &str {
+ /// "I'm the superhero of errors!"
+ /// }
+ ///
+ /// fn cause(&self) -> Option<&Error> {
+ /// Some(&self.side)
+ /// }
+ /// }
+ ///
+ /// #[derive(Debug)]
+ /// struct SuperErrorSideKick;
+ ///
+ /// impl fmt::Display for SuperErrorSideKick {
+ /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ /// write!(f, "SuperErrorSideKick is here!")
+ /// }
+ /// }
+ ///
+ /// impl Error for SuperErrorSideKick {
+ /// fn description(&self) -> &str {
+ /// "I'm SuperError side kick!"
+ /// }
+ /// }
+ ///
+ /// fn get_super_error() -> Result<(), SuperError> {
+ /// Err(SuperError { side: SuperErrorSideKick })
+ /// }
+ ///
+ /// fn main() {
+ /// match get_super_error() {
+ /// Err(e) => {
+ /// println!("Error: {}", e.description());
+ /// println!("Caused by: {}", e.cause().unwrap());
+ /// }
+ /// _ => println!("No error"),
+ /// }
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cause(&self) -> Option<&Error> { None }
+
+ /// Get the `TypeId` of `self`
+ #[doc(hidden)]
+ #[unstable(feature = "error_type_id",
+ reason = "unclear whether to commit to this public implementation detail",
+ issue = "27745")]
+ fn type_id(&self) -> TypeId where Self: 'static {
+ TypeId::of::<Self>()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
+ fn from(err: E) -> Box<Error + 'a> {
+ Box::new(err)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<Error + Send + Sync + 'a> {
+ fn from(err: E) -> Box<Error + Send + Sync + 'a> {
+ Box::new(err)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl From<String> for Box<Error + Send + Sync> {
+ fn from(err: String) -> Box<Error + Send + Sync> {
+ #[derive(Debug)]
+ struct StringError(String);
+
+ impl Error for StringError {
+ fn description(&self) -> &str { &self.0 }
+ }
+
+ impl Display for StringError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+ }
+
+ Box::new(StringError(err))
+ }
+}
+
+#[stable(feature = "string_box_error", since = "1.7.0")]
+impl From<String> for Box<Error> {
+ fn from(str_err: String) -> Box<Error> {
+ let err1: Box<Error + Send + Sync> = From::from(str_err);
+ let err2: Box<Error> = err1;
+ err2
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> {
+ fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> {
+ From::from(String::from(err))
+ }
+}
+
+#[stable(feature = "string_box_error", since = "1.7.0")]
+impl<'a> From<&'a str> for Box<Error> {
+ fn from(err: &'a str) -> Box<Error> {
+ From::from(String::from(err))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for str::ParseBoolError {
+ fn description(&self) -> &str { "failed to parse bool" }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for str::Utf8Error {
+ fn description(&self) -> &str {
+ "invalid utf-8: corrupt contents"
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for num::ParseIntError {
+ fn description(&self) -> &str {
+ self.__description()
+ }
+}
+
+#[unstable(feature = "try_from", issue = "33417")]
+impl Error for num::TryFromIntError {
+ fn description(&self) -> &str {
+ self.__description()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for num::ParseFloatError {
+ fn description(&self) -> &str {
+ self.__description()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for string::FromUtf8Error {
+ fn description(&self) -> &str {
+ "invalid utf-8"
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for string::FromUtf16Error {
+ fn description(&self) -> &str {
+ "invalid utf-16"
+ }
+}
+
+#[stable(feature = "str_parse_error2", since = "1.8.0")]
+impl Error for string::ParseError {
+ fn description(&self) -> &str {
+ match *self {}
+ }
+}
+
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+impl Error for char::DecodeUtf16Error {
+ fn description(&self) -> &str {
+ "unpaired surrogate found"
+ }
+}
+
+#[stable(feature = "box_error", since = "1.7.0")]
+impl<T: Error> Error for Box<T> {
+ fn description(&self) -> &str {
+ Error::description(&**self)
+ }
+
+ fn cause(&self) -> Option<&Error> {
+ Error::cause(&**self)
+ }
+}
+
+#[stable(feature = "fmt_error", since = "1.11.0")]
+impl Error for fmt::Error {
+ fn description(&self) -> &str {
+ "an error occurred when formatting an argument"
+ }
+}
+
+#[stable(feature = "try_borrow", since = "1.13.0")]
+impl Error for cell::BorrowError {
+ fn description(&self) -> &str {
+ "already mutably borrowed"
+ }
+}
+
+#[stable(feature = "try_borrow", since = "1.13.0")]
+impl Error for cell::BorrowMutError {
+ fn description(&self) -> &str {
+ "already borrowed"
+ }
+}
+
+#[unstable(feature = "try_from", issue = "33417")]
+impl Error for char::CharTryFromError {
+ fn description(&self) -> &str {
+ "converted integer out of range for `char`"
+ }
+}
+
+// copied from any.rs
+impl Error + 'static {
+ /// Returns true if the boxed type is the same as `T`
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn is<T: Error + 'static>(&self) -> bool {
+ // Get TypeId of the type this function is instantiated with
+ let t = TypeId::of::<T>();
+
+ // Get TypeId of the type in the trait object
+ let boxed = self.type_id();
+
+ // Compare both TypeIds on equality
+ t == boxed
+ }
+
+ /// Returns some reference to the boxed value if it is of type `T`, or
+ /// `None` if it isn't.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
+ if self.is::<T>() {
+ unsafe {
+ Some(&*(self as *const Error as *const T))
+ }
+ } else {
+ None
+ }
+ }
+
+ /// Returns some mutable reference to the boxed value if it is of type `T`, or
+ /// `None` if it isn't.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
+ if self.is::<T>() {
+ unsafe {
+ Some(&mut *(self as *mut Error as *mut T))
+ }
+ } else {
+ None
+ }
+ }
+}
+
+impl Error + 'static + Send {
+ /// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn is<T: Error + 'static>(&self) -> bool {
+ <Error + 'static>::is::<T>(self)
+ }
+
+ /// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
+ <Error + 'static>::downcast_ref::<T>(self)
+ }
+
+ /// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
+ <Error + 'static>::downcast_mut::<T>(self)
+ }
+}
+
+impl Error + 'static + Send + Sync {
+ /// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn is<T: Error + 'static>(&self) -> bool {
+ <Error + 'static>::is::<T>(self)
+ }
+
+ /// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
+ <Error + 'static>::downcast_ref::<T>(self)
+ }
+
+ /// Forwards to the method defined on the type `Any`.
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ #[inline]
+ pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
+ <Error + 'static>::downcast_mut::<T>(self)
+ }
+}
+
+impl Error {
+ #[inline]
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ /// Attempt to downcast the box to a concrete type.
+ pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> {
+ if self.is::<T>() {
+ unsafe {
+ let raw: *mut Error = Box::into_raw(self);
+ Ok(Box::from_raw(raw as *mut T))
+ }
+ } else {
+ Err(self)
+ }
+ }
+}
+
+impl Error + Send {
+ #[inline]
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ /// Attempt to downcast the box to a concrete type.
+ pub fn downcast<T: Error + 'static>(self: Box<Self>)
+ -> Result<Box<T>, Box<Error + Send>> {
+ let err: Box<Error> = self;
+ <Error>::downcast(err).map_err(|s| unsafe {
+ // reapply the Send marker
+ transmute::<Box<Error>, Box<Error + Send>>(s)
+ })
+ }
+}
+
+impl Error + Send + Sync {
+ #[inline]
+ #[stable(feature = "error_downcast", since = "1.3.0")]
+ /// Attempt to downcast the box to a concrete type.
+ pub fn downcast<T: Error + 'static>(self: Box<Self>)
+ -> Result<Box<T>, Box<Self>> {
+ let err: Box<Error> = self;
+ <Error>::downcast(err).map_err(|s| unsafe {
+ // reapply the Send+Sync marker
+ transmute::<Box<Error>, Box<Error + Send + Sync>>(s)
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::Error;
+ use fmt;
+
+ #[derive(Debug, PartialEq)]
+ struct A;
+ #[derive(Debug, PartialEq)]
+ struct B;
+
+ impl fmt::Display for A {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "A")
+ }
+ }
+ impl fmt::Display for B {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "B")
+ }
+ }
+
+ impl Error for A {
+ fn description(&self) -> &str { "A-desc" }
+ }
+ impl Error for B {
+ fn description(&self) -> &str { "A-desc" }
+ }
+
+ #[test]
+ fn downcasting() {
+ let mut a = A;
+ let mut a = &mut a as &mut (Error + 'static);
+ assert_eq!(a.downcast_ref::<A>(), Some(&A));
+ assert_eq!(a.downcast_ref::<B>(), None);
+ assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
+ assert_eq!(a.downcast_mut::<B>(), None);
+
+ let a: Box<Error> = Box::new(A);
+ match a.downcast::<B>() {
+ Ok(..) => panic!("expected error"),
+ Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),
+ }
+ }
+}