Skip to content

Commit

Permalink
Add no_std support
Browse files Browse the repository at this point in the history
Introduce no_std feature which, when enabled, uses core::error::Error
trait rather than std::error::Error and thus makes it possible to use
the crate in no_std builds.

Importantly though, using core::error module requires a unstable
error_in_core feature thus enabling no_std requires building with
nightly compiler.

Furthermore, enabling `no_std` disables handling of Backtrace fields
and support for displaying paths.  Since those types aren’t available
in no_std environments this shouldn’t be an issue.
  • Loading branch information
mina86 committed Aug 7, 2023
1 parent e3d16e5 commit 4687902
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 29 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ members = ["impl"]
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"]

[features]
no_std = []
2 changes: 1 addition & 1 deletion src/aserror.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::__private::Error;
use std::panic::UnwindSafe;
use core::panic::UnwindSafe;

pub trait AsDynError<'a>: Sealed {
fn as_dyn_error(&self) -> &(dyn Error + 'a);
Expand Down
58 changes: 31 additions & 27 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::fmt::Display;
use std::path::{Path, PathBuf};
use core::fmt::Display;

pub trait AsDisplay {
type Target: Display + ?Sized;
Expand All @@ -15,39 +14,44 @@ impl<T: Display> AsDisplay for &T {
}
}

impl AsDisplay for Path {
type Target = PathDisplay;
#[cfg(not(feature = "no_std"))]
mod path {
use std::path::{Path, PathBuf};

#[inline(always)]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self)
impl super::AsDisplay for Path {
type Target = PathDisplay;

#[inline(always)]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self)
}
}
}

impl AsDisplay for PathBuf {
type Target = PathDisplay;
impl super::AsDisplay for PathBuf {
type Target = PathDisplay;

#[inline(always)]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self.as_path())
#[inline(always)]
fn as_display(&self) -> &Self::Target {
PathDisplay::new(self.as_path())
}
}
}

#[repr(transparent)]
pub struct PathDisplay(Path);
#[repr(transparent)]
pub struct PathDisplay(Path);

impl PathDisplay {
#[inline(always)]
fn new(path: &Path) -> &Self {
// SAFETY: PathDisplay is repr(transparent) so casting pointers between
// it and its payload is safe.
unsafe { &*(path as *const Path as *const Self) }
impl PathDisplay {
#[inline(always)]
fn new(path: &Path) -> &Self {
// SAFETY: PathDisplay is repr(transparent) so casting pointers
// between it and its payload is safe.
unsafe { &*(path as *const Path as *const Self) }
}
}
}

impl Display for PathDisplay {
#[inline(always)]
fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> std::fmt::Result {
self.0.display().fmt(fmtr)
impl core::fmt::Display for PathDisplay {
#[inline(always)]
fn fmt(&self, fmtr: &mut core::fmt::Formatter) -> core::fmt::Result {
self.0.display().fmt(fmtr)
}
}
}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@
clippy::wildcard_imports,
)]
#![cfg_attr(provide_any, feature(provide_any))]
#![cfg_attr(feature = "no_std", feature(error_in_core))]
#![cfg_attr(feature = "no_std", no_std)]

mod aserror;
mod display;
Expand All @@ -252,5 +254,8 @@ pub mod __private {
pub use crate::display::AsDisplay;
#[cfg(provide_any)]
pub use crate::provide::ThiserrorProvide;
#[cfg(feature = "no_std")]
pub use core::error::Error;
#[cfg(not(feature = "no_std"))]
pub use std::error::Error;
}
2 changes: 1 addition & 1 deletion src/provide.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::any::{Demand, Provider};
use core::any::{Demand, Provider};

pub trait ThiserrorProvide: Sealed {
fn thiserror_provide<'a>(&'a self, demand: &mut Demand<'a>);
Expand Down

0 comments on commit 4687902

Please sign in to comment.