Skip to content
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

Add const accessors for data #56

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 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
80 changes: 72 additions & 8 deletions src/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ where
pub fn into_owned(self) -> T::Owned {
let cow = ManuallyDrop::new(self);

match cow.capacity() {
match cow.get_capacity() {
Some(capacity) => unsafe { T::owned_from_parts::<U>(cow.ptr, cow.fat, capacity) },
None => unsafe { &*T::ref_from_parts::<U>(cow.ptr, cow.fat) }.to_owned(),
}
Expand All @@ -106,7 +106,7 @@ where
/// Panics: If the data is owned.
#[inline]
pub fn unwrap_borrowed(self) -> &'a T {
if self.capacity().is_some() {
if self.get_capacity().is_some() {
panic!("Can not turn owned beef::Cow into a borrowed value")
}
unsafe { &*T::ref_from_parts::<U>(self.ptr, self.fat) }
Expand All @@ -129,7 +129,7 @@ where
/// ```
#[inline]
pub fn is_borrowed(&self) -> bool {
self.capacity().is_none()
self.get_capacity().is_none()
}

/// Returns `true` if data is owned and has non-0 capacity.
Expand All @@ -149,7 +149,7 @@ where
/// ```
#[inline]
pub fn is_owned(&self) -> bool {
self.capacity().is_some()
self.get_capacity().is_some()
}

/// Internal convenience method for casting `ptr` into a `&T`
Expand All @@ -159,9 +159,73 @@ where
}

#[inline]
fn capacity(&self) -> Option<U::NonZero> {
fn get_capacity(&self) -> Option<U::NonZero> {
U::maybe(self.fat, self.cap)
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just had to rename the existing internal method to something else.


/// Returns a pointer to underlying data
#[inline]
pub const fn as_ptr(&self) -> NonNull<T::PointerT> {
self.ptr
}
}

impl<'a, T> Cow<'a, T, Wide>
where
T: Beef + ?Sized,
{
/// Returns `true` if the contained data is empty
pub const fn is_empty(&self) -> bool {
self.len() == 0
}

/// Returns length of underlying data
#[inline]
pub const fn len(&self) -> usize {
self.fat
}

/// Returns capacity of underlying data
#[inline]
pub const fn capacity(&self) -> Option<usize> {
match self.cap {
Some(_) => unsafe {
// SAFETY: Transmute from Option<NonZero<usize>> to usize is
// sound by definition.
Some(core::mem::transmute::<
Option<core::num::NonZero<usize>>,
usize,
>(self.cap))
},
None => None,
}
}
}
impl<'a, T> Cow<'a, T, Lean>
where
T: Beef + ?Sized,
{
/// Returns `true` if the contained data is empty
pub const fn is_empty(&self) -> bool {
self.len() == 0
}

/// Returns length of underlying data
#[inline]
pub const fn len(&self) -> usize {
Lean::mask_len(self.fat)
}

/// Returns capacity of underlying data
#[inline]
pub const fn capacity(&self) -> Option<usize> {
let cap = Lean::mask_cap(self.fat);
if cap == 0 {
None
} else {
Some(cap)
}
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After using my version with as_ptr I realized it's only useful if one has externally stored length (in my case I took a string until separator). But if not, just the pointer without length doesn't help with constructing strings in const context.

I added these additional functions to allow access to all information. I'm not 100% familiar with the library internals so let me know whether they are correct.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, whether Lean capacity is correct - is it 0 for borrowed values?

Added mask_cap does (value & MASK_HI) >> 4.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it 0 for borrowed values?

Correct


impl<'a> Cow<'a, str, Wide> {
Expand Down Expand Up @@ -370,7 +434,7 @@ where
{
#[inline]
fn drop(&mut self) {
if let Some(capacity) = self.capacity() {
if let Some(capacity) = self.get_capacity() {
unsafe { T::owned_from_parts::<U>(self.ptr, self.fat, capacity) };
}
}
Expand All @@ -383,7 +447,7 @@ where
{
#[inline]
fn clone(&self) -> Self {
match self.capacity() {
match self.get_capacity() {
Some(_) => Cow::owned(self.borrow().to_owned()),
None => Cow { ..*self },
}
Expand Down Expand Up @@ -448,7 +512,7 @@ where
fn from(cow: Cow<'a, T, U>) -> Self {
let cow = ManuallyDrop::new(cow);

match cow.capacity() {
match cow.get_capacity() {
Some(capacity) => {
StdCow::Owned(unsafe { T::owned_from_parts::<U>(cow.ptr, cow.fat, capacity) })
}
Expand Down
4 changes: 4 additions & 0 deletions src/lean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ impl Lean {
pub const fn mask_len(len: usize) -> usize {
len & MASK_LO
}
#[inline]
pub const fn mask_cap(cap: usize) -> usize {
(cap & MASK_HI) >> 4
}
}

impl InternalCapacity for Lean {
Expand Down