Skip to content

Commit

Permalink
Make #![no_std] compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
Kijewski committed Dec 21, 2024
1 parent f00e5e2 commit bedc317
Show file tree
Hide file tree
Showing 19 changed files with 270 additions and 1,318 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.80.0"
toolchain: "1.81.0"
- run: cargo check --lib -p rinja --all-features

Audit:
Expand Down
13 changes: 7 additions & 6 deletions rinja/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0"
workspace = ".."
readme = "../README.md"
edition = "2021"
rust-version = "1.80"
rust-version = "1.81"

[package.metadata.docs.rs]
features = ["full"]
Expand All @@ -21,20 +21,21 @@ rustdoc-args = ["--generate-link-to-definition", "--cfg=docsrs"]
maintenance = { status = "actively-developed" }

[features]
default = ["config", "urlencode"]
default = ["config", "std", "urlencode"]
alloc = ["rinja_derive/alloc", "serde?/alloc", "serde_json?/alloc", "percent-encoding?/alloc"]
full = ["default", "code-in-doc", "serde_json"]
code-in-doc = ["rinja_derive/code-in-doc"]
config = ["rinja_derive/config"]
serde_json = ["rinja_derive/serde_json", "dep:serde", "dep:serde_json"]
std = ["alloc", "rinja_derive/std", "serde?/std", "serde_json?/std", "percent-encoding?/std"]
urlencode = ["rinja_derive/urlencode", "dep:percent-encoding"]

[dependencies]
rinja_derive = { version = "=0.3.5", path = "../rinja_derive" }

num-traits = { version = "0.2.6", optional = true }
percent-encoding = { version = "2.1.0", optional = true }
serde = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true }
percent-encoding = { version = "2.1.0", optional = true, default-features = false }
serde = { version = "1.0", optional = true, default-features = false }
serde_json = { version = "1.0", optional = true, default-features = false, features = [] }

itoa = "1.0.11"

Expand Down
58 changes: 43 additions & 15 deletions rinja/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::convert::Infallible;
use std::error::Error as StdError;
use std::{fmt, io};
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
use core::convert::Infallible;
use core::error::Error as StdError;
use core::fmt;
#[cfg(feature = "std")]
use std::io;

/// The [`Result`](std::result::Result) type with [`Error`] as default error type
pub type Result<I, E = Error> = std::result::Result<I, E>;
pub type Result<I, E = Error> = core::result::Result<I, E>;

/// rinja's error type
///
Expand All @@ -15,6 +19,7 @@ pub enum Error {
/// Generic, unspecified formatting error
Fmt,
/// An error raised by using `?` in a template
#[cfg(feature = "alloc")]
Custom(Box<dyn StdError + Send + Sync>),
/// JSON conversion error
#[cfg(feature = "serde_json")]
Expand All @@ -24,12 +29,14 @@ pub enum Error {
impl Error {
/// Capture an [`StdError`]
#[inline]
#[cfg(feature = "alloc")]
pub fn custom(err: impl Into<Box<dyn StdError + Send + Sync>>) -> Self {
Self::Custom(err.into())
}

/// Convert this [`Error`] into a
/// <code>[Box]&lt;dyn [StdError] + [Send] + [Sync]&gt;</code>
#[cfg(feature = "alloc")]
pub fn into_box(self) -> Box<dyn StdError + Send + Sync> {
match self {
Error::Fmt => fmt::Error.into(),
Expand All @@ -42,6 +49,7 @@ impl Error {
/// Convert this [`Error`] into an [`io::Error`]
///
/// Not this error itself, but the contained [`source`][StdError::source] is returned.
#[cfg(feature = "std")]
pub fn into_io_error(self) -> io::Error {
io::Error::other(match self {
Error::Custom(err) => match err.downcast() {
Expand All @@ -57,6 +65,7 @@ impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Error::Fmt => Some(&fmt::Error),
#[cfg(feature = "alloc")]
Error::Custom(err) => Some(err.as_ref()),
#[cfg(feature = "serde_json")]
Error::Json(err) => Some(err),
Expand All @@ -68,6 +77,7 @@ impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Fmt => fmt::Error.fmt(f),
#[cfg(feature = "alloc")]
Error::Custom(err) => err.fmt(f),
#[cfg(feature = "serde_json")]
Error::Json(err) => err.fmt(f),
Expand All @@ -82,6 +92,7 @@ impl From<Error> for fmt::Error {
}
}

#[cfg(feature = "std")]
impl From<Error> for io::Error {
#[inline]
fn from(err: Error) -> Self {
Expand All @@ -97,6 +108,7 @@ impl From<fmt::Error> for Error {
}

/// This conversion inspects the argument and chooses the best fitting [`Error`] variant
#[cfg(feature = "alloc")]
impl From<Box<dyn StdError + Send + Sync>> for Error {
#[inline]
fn from(err: Box<dyn StdError + Send + Sync>) -> Self {
Expand All @@ -105,19 +117,24 @@ impl From<Box<dyn StdError + Send + Sync>> for Error {
}

/// This conversion inspects the argument and chooses the best fitting [`Error`] variant
#[cfg(feature = "std")]
impl From<io::Error> for Error {
#[inline]
fn from(err: io::Error) -> Self {
from_from_io_error(err, MAX_ERROR_UNWRAP_COUNT)
}
}

#[cfg(feature = "alloc")]
const MAX_ERROR_UNWRAP_COUNT: usize = 5;

#[cfg(feature = "alloc")]
fn error_from_stderror(err: Box<dyn StdError + Send + Sync>, unwraps: usize) -> Error {
let Some(unwraps) = unwraps.checked_sub(1) else {
return Error::Custom(err);
};
#[cfg(not(feature = "std"))]
let _ = unwraps;
match ErrorKind::inspect(err.as_ref()) {
ErrorKind::Fmt => Error::Fmt,
ErrorKind::Custom => Error::Custom(err),
Expand All @@ -126,6 +143,7 @@ fn error_from_stderror(err: Box<dyn StdError + Send + Sync>, unwraps: usize) ->
Ok(err) => Error::Json(*err),
Err(_) => Error::Fmt, // unreachable
},
#[cfg(feature = "std")]
ErrorKind::Io => match err.downcast() {
Ok(err) => from_from_io_error(*err, unwraps),
Err(_) => Error::Fmt, // unreachable
Expand All @@ -137,6 +155,7 @@ fn error_from_stderror(err: Box<dyn StdError + Send + Sync>, unwraps: usize) ->
}
}

#[cfg(feature = "std")]
fn from_from_io_error(err: io::Error, unwraps: usize) -> Error {
let Some(inner) = err.get_ref() else {
return Error::custom(err);
Expand Down Expand Up @@ -169,30 +188,39 @@ fn from_from_io_error(err: io::Error, unwraps: usize) -> Error {
}
}

#[cfg(feature = "alloc")]
enum ErrorKind {
Fmt,
Custom,
#[cfg(feature = "serde_json")]
Json,
#[cfg(feature = "std")]
Io,
Rinja,
}

#[cfg(feature = "alloc")]
impl ErrorKind {
fn inspect(err: &(dyn StdError + 'static)) -> ErrorKind {
if err.is::<fmt::Error>() {
ErrorKind::Fmt
} else if err.is::<io::Error>() {
ErrorKind::Io
} else if err.is::<Error>() {
ErrorKind::Rinja
} else {
#[cfg(feature = "serde_json")]
if err.is::<serde_json::Error>() {
return ErrorKind::Json;
}
ErrorKind::Custom
return ErrorKind::Fmt;
}

#[cfg(feature = "std")]
if err.is::<io::Error>() {
return ErrorKind::Io;
}

if err.is::<Error>() {
return ErrorKind::Rinja;
}

#[cfg(feature = "serde_json")]
if err.is::<serde_json::Error>() {
return ErrorKind::Json;
}

ErrorKind::Custom
}
}

Expand Down
Loading

0 comments on commit bedc317

Please sign in to comment.