From 8c5d4022a9b4c173afe560daa55718ee1686ea6f Mon Sep 17 00:00:00 2001 From: tormol Date: Sun, 20 Sep 2020 00:42:10 +0200 Subject: [PATCH 1/2] Add alloc feature which enables AsciiStriing but not Error or CStr --- Cargo.toml | 3 ++- README.md | 17 ++++++++++------- src/ascii_str.rs | 25 ++++++++++++++++--------- src/ascii_string.rs | 34 +++++++++++++++++++++++++--------- src/lib.rs | 7 +++++-- 5 files changed, 58 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6665f6a..0956bb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,8 @@ serde_test = { version = "1.0", optional = true } [features] default = ["std"] -std = [] +std = ["alloc"] +alloc = [] [[test]] name = "tests" diff --git a/README.md b/README.md index 092e439..b7dc1bb 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,20 @@ ascii = "1.0" Most of `AsciiChar` and `AsciiStr` can be used without `std` by disabling the default features. The owned string type `AsciiString` and the conversion trait -`IntoAsciiString` as well as all methods referring to these types and -`CStr` and `CString` are unavailable. -The `Error` trait is also unavailable, but `description()` is made -available as an inherent method for `ToAsciiCharError` and `AsAsciiStrError`. +`IntoAsciiString` as well as all methods referring to these types can be +re-enabled by enabling the `alloc` feature. -To use the `ascii` crate in `core`-only mode in your cargo project just add the -following dependency declaration in `Cargo.toml`: +Methods referring to `CStr` and `CString` are also unavailable. +The `Error` trait also only exists in `std`, but `description()` is made +available as an inherent method for `ToAsciiCharError` and `AsAsciiStrError` +in `#![no_std]`-mode. + +To use the `ascii` crate in `#![no_std]` mode in your cargo project, +just add the following dependency declaration in `Cargo.toml`: ```toml [dependencies] -ascii = { version = "1.0", default-features = false } +ascii = { version = "1.0", default-features = false, features = ["alloc"] } ``` ## Minimum supported Rust version diff --git a/src/ascii_str.rs b/src/ascii_str.rs index 208e9a3..1a2fdf9 100644 --- a/src/ascii_str.rs +++ b/src/ascii_str.rs @@ -1,3 +1,7 @@ +#[cfg(feature = "alloc")] +use alloc::borrow::ToOwned; +#[cfg(feature = "alloc")] +use alloc::boxed::Box; use core::fmt; use core::ops::{Index, IndexMut}; use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; @@ -8,7 +12,7 @@ use std::error::Error; use std::ffi::CStr; use ascii_char::AsciiChar; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] use ascii_string::AsciiString; /// AsciiStr represents a byte or string slice that only contains ASCII characters. @@ -69,7 +73,7 @@ impl AsciiStr { } /// Copies the content of this `AsciiStr` into an owned `AsciiString`. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn to_ascii_string(&self) -> AsciiString { AsciiString::from(self.slice.to_vec()) } @@ -241,7 +245,7 @@ impl AsciiStr { } /// Returns a copy of this string where letters 'a' to 'z' are mapped to 'A' to 'Z'. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn to_ascii_uppercase(&self) -> AsciiString { let mut ascii_string = self.to_ascii_string(); ascii_string.make_ascii_uppercase(); @@ -249,7 +253,7 @@ impl AsciiStr { } /// Returns a copy of this string where letters 'A' to 'Z' are mapped to 'a' to 'z'. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn to_ascii_lowercase(&self) -> AsciiString { let mut ascii_string = self.to_ascii_string(); ascii_string.make_ascii_lowercase(); @@ -290,7 +294,7 @@ impl_partial_eq! {str} impl_partial_eq! {[u8]} impl_partial_eq! {[AsciiChar]} -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl ToOwned for AsciiStr { type Owned = AsciiString; @@ -345,7 +349,7 @@ impl<'a> From<&'a mut [AsciiChar]> for &'a mut AsciiStr { unsafe { &mut *ptr } } } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl From> for Box { #[inline] fn from(owned: Box<[AsciiChar]>) -> Box { @@ -405,7 +409,7 @@ impl<'a> From<&'a AsciiStr> for &'a str { } macro_rules! widen_box { ($wider: ty) => { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] impl From> for Box<$wider> { #[inline] fn from(owned: Box) -> Box<$wider> { @@ -1065,6 +1069,9 @@ impl AsAsciiStr for CStr { #[cfg(test)] mod tests { use super::{AsAsciiStr, AsAsciiStrError, AsMutAsciiStr, AsciiStr}; + use alloc::string::{String, ToString}; + #[cfg(feature = "alloc")] + use alloc::vec::Vec; use AsciiChar; #[test] @@ -1155,7 +1162,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn as_mut_ascii_str() { macro_rules! err {{$i:expr} => {Err(AsAsciiStrError($i))}} let mut s: String = "abčd".to_string(); @@ -1234,7 +1241,7 @@ mod tests { } #[test] - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_ascii_case() { let bytes = ([b'a', b'@', b'A'], [b'A', b'@', b'a']); let a = bytes.0.as_ascii_str().unwrap(); diff --git a/src/ascii_string.rs b/src/ascii_string.rs index 564e3f2..e3bb42f 100644 --- a/src/ascii_string.rs +++ b/src/ascii_string.rs @@ -1,11 +1,17 @@ -use std::any::Any; -use std::borrow::{Borrow, BorrowMut, Cow}; +use alloc::borrow::{Borrow, BorrowMut, Cow, ToOwned}; +use alloc::fmt; +use alloc::string::String; +use alloc::vec::Vec; +#[cfg(feature = "std")] +use core::any::Any; +use core::iter::FromIterator; +use core::mem; +use core::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut}; +use core::str::FromStr; +#[cfg(feature = "std")] use std::error::Error; +#[cfg(feature = "std")] use std::ffi::{CStr, CString}; -use std::iter::FromIterator; -use std::ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut}; -use std::str::FromStr; -use std::{fmt, mem}; use ascii_char::AsciiChar; use ascii_str::{AsAsciiStr, AsAsciiStrError, AsciiStr}; @@ -670,6 +676,7 @@ impl fmt::Display for FromAsciiError { fmt::Display::fmt(&self.error, fmtr) } } +#[cfg(feature = "std")] impl Error for FromAsciiError { #[inline] fn description(&self) -> &str { @@ -759,6 +766,7 @@ impl_into_ascii_string! {String} impl_into_ascii_string! {'a, &'a str} /// Note that the trailing null byte will be removed in the conversion. +#[cfg(feature = "std")] impl IntoAsciiString for CString { #[inline] unsafe fn into_ascii_string_unchecked(self) -> AsciiString { @@ -786,6 +794,7 @@ impl IntoAsciiString for CString { } /// Note that the trailing null byte will be removed in the conversion. +#[cfg(feature = "std")] impl<'a> IntoAsciiString for &'a CStr { #[inline] unsafe fn into_ascii_string_unchecked(self) -> AsciiString { @@ -841,9 +850,14 @@ where #[cfg(test)] mod tests { - use super::{AsciiString, IntoAsciiString}; + use super::AsciiString; + #[cfg(feature = "std")] + use super::IntoAsciiString; + use alloc::str::FromStr; + use alloc::string::{String, ToString}; + use alloc::vec::Vec; + #[cfg(feature = "std")] use std::ffi::CString; - use std::str::FromStr; use AsciiChar; #[test] @@ -868,6 +882,7 @@ mod tests { } #[test] + #[cfg(feature = "std")] fn from_cstring() { let cstring = CString::new("baz").unwrap(); let ascii_str = cstring.clone().into_ascii_string().unwrap(); @@ -887,6 +902,7 @@ mod tests { } #[test] + #[cfg(feature = "std")] fn fmt_ascii_string() { let s = "abc".to_string().into_ascii_string().unwrap(); assert_eq!(format!("{}", s), "abc".to_string()); @@ -895,7 +911,7 @@ mod tests { #[test] fn write_fmt() { - use std::{fmt, str}; + use alloc::{fmt, str}; let mut s0 = AsciiString::new(); fmt::write(&mut s0, format_args!("Hello World")).unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 4c77509..85138b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::trivially_copy_pass_by_ref)] // for compatibility with methods on char and u8 +#[cfg(feature = "alloc")] +#[cfg_attr(test, macro_use)] +extern crate alloc; #[cfg(feature = "std")] extern crate core; @@ -42,7 +45,7 @@ extern crate serde_test; mod ascii_char; mod ascii_str; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] mod ascii_string; mod free_functions; #[cfg(feature = "serde")] @@ -51,6 +54,6 @@ mod serialization; pub use ascii_char::{AsciiChar, ToAsciiChar, ToAsciiCharError}; pub use ascii_str::{AsAsciiStr, AsAsciiStrError, AsMutAsciiStr, AsciiStr}; pub use ascii_str::{Chars, CharsMut, CharsRef}; -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub use ascii_string::{AsciiString, FromAsciiError, IntoAsciiString}; pub use free_functions::{caret_decode, caret_encode}; From 2098d7f4d575daa1fa76af15bb94be13a5154527 Mon Sep 17 00:00:00 2001 From: Thomas Bahn Date: Sun, 11 Oct 2020 21:54:50 +0200 Subject: [PATCH 2/2] Update src/ascii_str.rs --- src/ascii_str.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ascii_str.rs b/src/ascii_str.rs index 1a2fdf9..1bf6383 100644 --- a/src/ascii_str.rs +++ b/src/ascii_str.rs @@ -1069,6 +1069,7 @@ impl AsAsciiStr for CStr { #[cfg(test)] mod tests { use super::{AsAsciiStr, AsAsciiStrError, AsMutAsciiStr, AsciiStr}; + #[cfg(feature = "alloc")] use alloc::string::{String, ToString}; #[cfg(feature = "alloc")] use alloc::vec::Vec;