-
-
Notifications
You must be signed in to change notification settings - Fork 17
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
base: master
Are you sure you want to change the base?
Conversation
Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
@Caellian I reckon if we don't want to confuse people by overloading methods on the underlying deref types, the idiomatic way of doing it is to not make it a method at all and instead of The first one of these is very analogous to what's going on here, so if you don't mind if it's "incredibly convoluted" 🙃 then |
Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
- Add is_empty as suggested by clippy. Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
src/generic.rs
Outdated
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) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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
src/generic.rs
Outdated
fn capacity(&self) -> Option<U::NonZero> { | ||
fn get_capacity(&self) -> Option<U::NonZero> { | ||
U::maybe(self.fat, self.cap) | ||
} |
There was a problem hiding this comment.
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.
Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
This looks like a solution to XY problem and I'm not really a big fan of leaking internals. If you just need a way to get a |
I don't see it as leaking internals as they don't expose something that will ever change, nor use internal types in signatures:
std Cow probably doesn't expose these methods because a large part of it was designed without const in mind, aannd once const traits land they would be just noise because those methods are always defined on cowed types as well. In case of a library they can be removed with a simple semver change.
The exposed functions are building blocks for functions like |
If you have
|
Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
I know that, but I don't. I forked this crate and made a PR because I'm using
I don't. I added it without thinking for completeness. |
My point is that if you have a const PTR: *mut u8 = COW_STR.as_str().as_ptr(); Likewise you don't need the Don't think there are any issues if we override |
It's not more versatile if it only works for #[repr(transparent)]
struct TagBorrowed {
name: [u8]
}
impl beef::generic::Beef for TagBorrowed {
// Assuming TagBorrowed isn't sealed
}
struct TagOwned {
name: alloc::string::String
}
impl core::ops::Deref for TagOwned {
type Target = TagBorrowed;
fn deref(&self) -> &Self::Target {
unsafe {
&*(self.name.as_bytes() as *const [u8] as *const TagBorrowed)
}
}
}
let example: beef::Cow<TagBorrowed> = beef::Cow::owned(TagOwned {
name: alloc::string::String::from("hui")
}); But that assumes beef::Cow can be used with types other than Something like #20 would be fine if it worked in |
I didn't want to use
as_ptr
because that exists onDeref
withstr
Target. I don't like this name, but it's very explicit and long so it won't be confused withstd
which doesn't useget_
.Alternatively, maybe
as_raw_ptr
would be good. But IMO it's way to similar toas_ptr
, so I opted forget_raw_ptr
because it's clear what it does and just enough imperfect/annoying to make collisions with Cowed types unlikely.Once const traits get into stable, this could maybe be deprecated and point to
str::as_ptr
oraddr_of!(**deref)
. But I feel like that won't be the case for additional 4-5 years.