-
-
Notifications
You must be signed in to change notification settings - Fork 16
Support private casts #9
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
Comments
It looks like rust-lang/rfcs#2529 is postponed. In light of that, would it make sense to implement this feature by generating an inherent impl with a private function in it, rather than a trait implementation? I don’t know anything about the implementation of My specific use case for this is making a newtype wrapper around |
I've since found a way for a private cast by using one extra indirection (and totally forgot about notifying this issue about it). #[derive(RefCast)]
#[repr(transparent)]
pub struct ethernet_frame(Private);
#[derive(RefCast)]
#[repr(transparent)]
struct Private([u8]);
impl ethernet_frame {
pub fn new(bytes: &[u8]) -> Option<&Self> {
if Self::valid(bytes) { // E.g. validate length, encoding, ...
Some(ethernet_frame::ref_cast(Private::ref_cast(bytes)))
} else {
None
}
}
} Since the type |
That was my first idea too, but it doesn’t work for me:
How did you make it work? |
Ah, yes, it needs to be pseudo-private, which is a bit of a hack. The type itself is qualified use ref_cast::RefCast;
#[derive(RefCast)]
#[repr(transparent)]
pub struct ethernet_frame(inner::Private);
mod inner {
use ref_cast::RefCast;
#[derive(RefCast)]
#[repr(transparent)]
pub struct Private([u8]);
}
impl ethernet_frame {
pub fn new(bytes: &[u8]) -> Option<&Self> {
if Self::valid(bytes) { // E.g. validate length, encoding, ...
Some(ethernet_frame::ref_cast(inner::Private::ref_cast(bytes)))
} else {
None
}
}
pub fn valid(bytes: &[u8]) -> bool { todo!() }
} |
Oh that’s perfect, thank you! Weird that this technique allows working around the private-leakage error, but I’ll take it. |
FWIW, there's a second (opt-in) warning, |
@HeroicKatora please note that it's not true. You can access type impls without being able to name type (you only need compiler to infer it): ethernet_frame::ref_cast(<_>::ref_cast(&[] as _));
ethernet_frame::ref_cast(RefCast::ref_cast(&[] as _)); |
@WaffleLapkin Ohhh, that's right. Hm, I guess you could create a fake second impl such that these aren't uniquely deducable? |
@HeroicKatora I don't think that's possible with |
I think that would be perfectly do-able by introducing a new attribute macro, which could be implemented in the same crate as the existing derive macro (and would mostly share the implementation). I imagine it would look like: [ref_cast]
[repr(transparent)]
struct EthernetFrame([u8]); which could expand to something like: [repr(transparent)]
struct EthernetFrame([u8]);
impl EthernetFrame{
fn ref_cast(from: &[u8]) -> &Self {
// same implementation as RefCast::ref_cast derived trait implementation
}
fn ref_cast_mut(from: &mut [u8]) -> &mut Self {
// same implementation as RefCast::ref_cast_mut derived trait implementation
}
} It could allow overriding the visibility of the generated functions, e.g. |
Uh oh!
There was an error while loading. Please reload this page.
This is related but not the same as #3. For many applications the reference cast is wanted in a safe interface but want to assert some invariants on an inner type in the process. It would be very useful to expose a converter that can only be used by the type itself, instead of always generating a trait which by definition can be used by all users.
The text was updated successfully, but these errors were encountered: