Skip to content

Commit

Permalink
0.4.2 (#27)
Browse files Browse the repository at this point in the history
* const_str working on stable

* Update Cargo.toml

* Fix const_fn on no_str
maciejhirsz authored Mar 31, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 87d8489 commit 9024b24
Showing 4 changed files with 108 additions and 11 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "beef"
version = "0.4.1"
version = "0.4.2"
authors = ["Maciej Hirsz <hello@maciej.codes>"]
edition = "2018"
description = "More compact Cow"
@@ -21,8 +21,8 @@ serde_json = "1.0"
[features]
default = []

# adds `Cow::const_str` and `Cow::const_slice`, which are const fn
# alternatives for creating &str and &[T] borrows
# adds `Cow::const_slice`, the const fn alternative to `Cow::borrowed` for
# generic &[T] slices.
# requires nightly: https://github.com/rust-lang/rust/issues/57563
const_fn = []

89 changes: 82 additions & 7 deletions src/generic.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,9 @@ use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr::NonNull;

#[cfg(target_pointer_width = "64")]
use crate::lean::internal::Lean;
use crate::wide::internal::Wide;
use crate::traits::{Beef, Capacity};

/// A clone-on-write smart pointer, mostly compatible with [`std::borrow::Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html).
@@ -161,13 +164,19 @@ where
}
}

// This requires nightly:
// https://github.com/rust-lang/rust/issues/57563
impl<'a> Cow<'a, str, crate::wide::internal::Wide> {
impl<'a> Cow<'a, str, Wide> {
/// Borrowed data.
///
/// Requires nightly. Currently not available for `beef::lean::Cow`.
#[cfg(feature = "const_fn")]
/// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
/// We use impl specialization to allow this function to be `const`.
///
/// # Example
///
/// ```rust
/// use beef::Cow;
///
/// const HELLO: Cow<str> = Cow::const_str("Hello");
/// ```
pub const fn const_str(val: &'a str) -> Self {
Cow {
// We are casting *const T to *mut T, however for all borrowed values
@@ -180,16 +189,51 @@ impl<'a> Cow<'a, str, crate::wide::internal::Wide> {
}
}

#[cfg(target_pointer_width = "64")]
impl<'a> Cow<'a, str, Lean> {
/// Borrowed data.
///
/// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
/// We use impl specialization to allow this function to be `const`.
///
/// # Example
///
/// ```rust
/// use beef::lean::Cow;
///
/// const HELLO: Cow<str> = Cow::const_str("Hello");
/// ```
pub const fn const_str(val: &'a str) -> Self {
Cow {
// We are casting *const T to *mut T, however for all borrowed values
// this raw pointer is only ever dereferenced back to &T.
ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut u8) },
fat: Lean::mask_len(val.len()),
cap: Lean,
marker: PhantomData,
}
}
}

// This requires nightly:
// https://github.com/rust-lang/rust/issues/57563
#[cfg(feature = "const_fn")]
impl<'a, T> Cow<'a, [T], crate::wide::internal::Wide>
impl<'a, T> Cow<'a, [T], Wide>
where
T: Clone,
{
/// Borrowed data.
///
/// Requires nightly. Currently not available for `beef::lean::Cow`.
/// This is functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
/// We use impl specialization to allow this function to be `const`.
///
/// # Example
///
/// ```rust
/// use beef::Cow;
///
/// const HELLO: Cow<[u8]> = Cow::const_slice(&[1, 2, 3]);
/// ```
pub const fn const_slice(val: &'a [T]) -> Self {
Cow {
// We are casting *const T to *mut T, however for all borrowed values
@@ -202,6 +246,37 @@ where
}
}

// This requires nightly:
// https://github.com/rust-lang/rust/issues/57563
#[cfg(all(feature = "const_fn", target_pointer_width = "64"))]
impl<'a, T> Cow<'a, [T], Lean>
where
T: Clone,
{
/// Borrowed data.
///
/// This i functionally identical to [`borrow`](./generic/struct.Cow.html#method.borrow).
/// We use impl specialization to allow this function to be `const`.
///
/// # Example
///
/// ```rust
/// use beef::lean::Cow;
///
/// const HELLO: Cow<[u8]> = Cow::const_slice(&[1, 2, 3]);
/// ```
pub const fn const_slice(val: &'a [T]) -> Self {
Cow {
// We are casting *const T to *mut T, however for all borrowed values
// this raw pointer is only ever dereferenced back to &T.
ptr: unsafe { NonNull::new_unchecked(val.as_ptr() as *mut T) },
fat: Lean::mask_len(val.len()),
cap: Lean,
marker: PhantomData,
}
}
}

impl<T, U> Hash for Cow<'_, T, U>
where
T: Hash + Beef + ?Sized,
9 changes: 8 additions & 1 deletion src/lean.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ use crate::traits::Capacity;
/// top level `beef::Cow` if you wish to avoid this problem.
pub type Cow<'a, T> = crate::generic::Cow<'a, T, Lean>;

mod internal {
pub(crate) mod internal {
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Lean;
}
@@ -21,6 +21,13 @@ use internal::Lean;
const MASK_LO: usize = u32::max_value() as usize;
const MASK_HI: usize = !(u32::max_value() as usize);

impl Lean {
#[inline]
pub const fn mask_len(len: usize) -> usize {
len & MASK_LO
}
}

impl Capacity for Lean {
type Field = Lean;
type NonZero = Lean;
15 changes: 15 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -206,6 +206,21 @@ macro_rules! test { ($tmod:ident => $cow:path) => {

assert_eq!(expected, cow.into_owned());
}

#[test]
fn const_fn_str() {
const HELLO: Cow<str> = Cow::const_str("Hello");

assert_eq!(&*HELLO, "Hello");
}

#[test]
#[cfg(feature = "const_fn")]
fn const_fn_slice() {
const FOO: Cow<[u8]> = Cow::const_slice(b"bar");

assert_eq!(&*FOO, b"bar");
}
}
} }

0 comments on commit 9024b24

Please sign in to comment.