Skip to content

Add alloc feature #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ serde_test = { version = "1.0", optional = true }

[features]
default = ["std"]
std = []
std = ["alloc"]
alloc = []

[[test]]
name = "tests"
Expand Down
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 17 additions & 9 deletions src/ascii_str.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -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.
Expand Down Expand Up @@ -77,7 +81,7 @@ impl AsciiStr {
}

/// Copies the content of this `AsciiStr` into an owned `AsciiString`.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
#[must_use]
pub fn to_ascii_string(&self) -> AsciiString {
AsciiString::from(self.slice.to_vec())
Expand Down Expand Up @@ -283,7 +287,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")]
#[must_use]
pub fn to_ascii_uppercase(&self) -> AsciiString {
let mut ascii_string = self.to_ascii_string();
Expand All @@ -292,7 +296,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")]
#[must_use]
pub fn to_ascii_lowercase(&self) -> AsciiString {
let mut ascii_string = self.to_ascii_string();
Expand Down Expand Up @@ -336,7 +340,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;

Expand Down Expand Up @@ -391,7 +395,7 @@ impl<'a> From<&'a mut [AsciiChar]> for &'a mut AsciiStr {
unsafe { &mut *ptr }
}
}
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
impl From<Box<[AsciiChar]>> for Box<AsciiStr> {
#[inline]
fn from(owned: Box<[AsciiChar]>) -> Box<AsciiStr> {
Expand Down Expand Up @@ -451,7 +455,7 @@ impl<'a> From<&'a AsciiStr> for &'a str {
}
macro_rules! widen_box {
($wider: ty) => {
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
impl From<Box<AsciiStr>> for Box<$wider> {
#[inline]
fn from(owned: Box<AsciiStr>) -> Box<$wider> {
Expand Down Expand Up @@ -1218,6 +1222,10 @@ 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;
use AsciiChar;

/// Ensures that common types, `str`, `[u8]`, `AsciiStr` and their
Expand Down Expand Up @@ -1330,7 +1338,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();
Expand Down Expand Up @@ -1409,7 +1417,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();
Expand Down
36 changes: 26 additions & 10 deletions src/ascii_string.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -699,6 +705,7 @@ impl<O> fmt::Display for FromAsciiError<O> {
fmt::Display::fmt(&self.error, fmtr)
}
}
#[cfg(feature = "std")]
impl<O: Any> Error for FromAsciiError<O> {
#[inline]
#[allow(deprecated)] // TODO: Remove deprecation once the earliest version we support deprecates this method.
Expand Down Expand Up @@ -799,7 +806,8 @@ impl_into_ascii_string! {String}
impl_into_ascii_string! {'a, &'a str}

/// # Notes
/// The trailing null byte `CString` has will be removed during this conversion
/// The trailing null byte `CString` has will be removed during this conversion.
#[cfg(feature = "std")]
impl IntoAsciiString for CString {
#[inline]
unsafe fn into_ascii_string_unchecked(self) -> AsciiString {
Expand All @@ -826,6 +834,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 {
Expand Down Expand Up @@ -885,9 +894,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]
Expand All @@ -912,6 +926,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();
Expand All @@ -932,6 +947,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());
Expand All @@ -940,7 +956,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();
Expand Down
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
// In preparation for feature `unsafe_block_in_unsafe_fn` (https://github.com/rust-lang/rust/issues/71668)
#![allow(unused_unsafe)]

#[cfg(feature = "alloc")]
#[cfg_attr(test, macro_use)]
extern crate alloc;
#[cfg(feature = "std")]
extern crate core;

Expand All @@ -65,7 +68,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")]
Expand All @@ -74,6 +77,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};