Skip to content

Commit

Permalink
crate: add 'alloc' feature
Browse files Browse the repository at this point in the history
This crate currently only has a 'std' feature and of course support for
no-std. But in that mode, it was also no-alloc. In practice, this crate
is virtually all core-only, that is, no-std and no-alloc. There are
really only a few parts that want std or alloc. For std, runtime CPU
feature detection requires it. For alloc, there are a few minor APIs
that require allocation.

Previously, the only way to get the APIs that require allocation was to
enable 'std'. This new feature permits getting those APIs without
bringing in 'std'.

I don't expect this to unlock any new or interesting use cases, but it
will make downstream configurations a little more sensible and less
annoying.

Fixes #121
  • Loading branch information
BurntSushi committed Jul 11, 2023
1 parent e49a1b8 commit 00c6372
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 22 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ jobs:
name: Show byte order for debugging
run: ${{ env.CARGO }} test --verbose $TARGET byte_order -- --nocapture
- if: matrix.build != 'pinned'
name: Run tests under default configuration
run: ${{ env.CARGO }} test --verbose $TARGET
- if: matrix.build != 'pinned'
name: Run tests with just alloc feature
run: ${{ env.CARGO }} test --verbose --no-default-features --features alloc $TARGET
- if: matrix.build == 'stable'
name: Run under different SIMD configurations
run: |
Expand Down
8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ default = ["std"]
# permits this crate to use runtime CPU feature detection to automatically
# accelerate searching via vector instructions. Without the standard library,
# this automatic detection is not possible.
std = []
std = ["alloc"]

# The 'alloc' feature enables some APIs that require allocation, such as
# 'Finder::into_owned'. Note that this feature does not enable runtime CPU
# feature detection. That still requires 'std'.
alloc = []

# The 'use_std' feature is DEPRECATED. It will be removed in memchr 3. Until
# then, it is alias for the 'std' feature.
use_std = ["std"]
Expand Down
26 changes: 14 additions & 12 deletions src/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ use core::ops;
#[derive(Clone, Debug)]
pub struct CowBytes<'a>(Imp<'a>);

// N.B. We don't use std::borrow::Cow here since we can get away with a
// N.B. We don't use alloc::borrow::Cow here since we can get away with a
// Box<[u8]> for our use case, which is 1/3 smaller than the Vec<u8> that
// a Cow<[u8]> would use.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
#[derive(Clone, Debug)]
enum Imp<'a> {
Borrowed(&'a [u8]),
Owned(Box<[u8]>),
Owned(alloc::boxed::Box<[u8]>),
}

#[cfg(not(feature = "std"))]
#[cfg(not(feature = "alloc"))]
#[derive(Clone, Debug)]
struct Imp<'a>(&'a [u8]);

Expand All @@ -40,9 +40,9 @@ impl<'a> CowBytes<'a> {
}

/// Create a new owned CowBytes.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
#[inline(always)]
pub fn new_owned(bytes: Box<[u8]>) -> CowBytes<'static> {
pub fn new_owned(bytes: alloc::boxed::Box<[u8]>) -> CowBytes<'static> {
CowBytes(Imp::Owned(bytes))
}

Expand All @@ -57,30 +57,32 @@ impl<'a> CowBytes<'a> {
///
/// If this is already an owned byte string internally, then this is a
/// no-op. Otherwise, the internal byte string is copied.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
#[inline(always)]
pub fn into_owned(self) -> CowBytes<'static> {
match self.0 {
Imp::Borrowed(b) => CowBytes::new_owned(Box::from(b)),
Imp::Borrowed(b) => {
CowBytes::new_owned(alloc::boxed::Box::from(b))
}
Imp::Owned(b) => CowBytes::new_owned(b),
}
}
}

impl<'a> Imp<'a> {
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
#[inline(always)]
pub fn new(bytes: &'a [u8]) -> Imp<'a> {
Imp::Borrowed(bytes)
}

#[cfg(not(feature = "std"))]
#[cfg(not(feature = "alloc"))]
#[inline(always)]
pub fn new(bytes: &'a [u8]) -> Imp<'a> {
Imp(bytes)
}

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
#[inline(always)]
pub fn as_slice(&self) -> &[u8] {
match self {
Expand All @@ -89,7 +91,7 @@ impl<'a> Imp<'a> {
}
}

#[cfg(not(feature = "std"))]
#[cfg(not(feature = "alloc"))]
#[inline(always)]
pub fn as_slice(&self) -> &[u8] {
self.0
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ standard library exposes a platform independent SIMD API.
)))]
compile_error!("memchr currently not supported on non-{16,32,64}");

#[cfg(feature = "alloc")]
extern crate alloc;

pub use crate::memchr::{
memchr, memchr2, memchr2_iter, memchr3, memchr3_iter, memchr_iter,
memrchr, memrchr2, memrchr2_iter, memrchr3, memrchr3_iter, memrchr_iter,
Expand Down
10 changes: 5 additions & 5 deletions src/memmem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,8 @@ impl<'h, 'n> FindIter<'h, 'n> {
/// If this is already an owned iterator, then this is a no-op. Otherwise,
/// this copies the needle.
///
/// This is only available when the `std` feature is enabled.
#[cfg(feature = "std")]
/// This is only available when the `alloc` feature is enabled.
#[cfg(feature = "alloc")]
#[inline]
pub fn into_owned(self) -> FindIter<'h, 'static> {
FindIter {
Expand Down Expand Up @@ -526,8 +526,8 @@ impl<'n> Finder<'n> {
/// If this is already an owned finder, then this is a no-op. Otherwise,
/// this copies the needle.
///
/// This is only available when the `std` feature is enabled.
#[cfg(feature = "std")]
/// This is only available when the `alloc` feature is enabled.
#[cfg(feature = "alloc")]
#[inline]
pub fn into_owned(self) -> Finder<'static> {
Finder { searcher: self.searcher.into_owned() }
Expand Down Expand Up @@ -921,7 +921,7 @@ impl<'n> Searcher<'n> {
}
}

#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
fn into_owned(self) -> Searcher<'static> {
use self::SearcherKind::*;

Expand Down
8 changes: 4 additions & 4 deletions src/memmem/x86/avx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ mod nostd {

impl Forward {
pub(crate) fn new(
ninfo: &NeedleInfo,
needle: &[u8],
_ninfo: &NeedleInfo,
_needle: &[u8],
) -> Option<Forward> {
None
}
Expand All @@ -92,8 +92,8 @@ mod nostd {

pub(crate) fn find(
&self,
haystack: &[u8],
needle: &[u8],
_haystack: &[u8],
_needle: &[u8],
) -> Option<usize> {
unreachable!()
}
Expand Down

0 comments on commit 00c6372

Please sign in to comment.