[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
|
|
Subscribe / Log in / New account

Constructor checking

Constructor checking

Posted Oct 24, 2024 19:01 UTC (Thu) by ringerc (subscriber, #3071)
In reply to: Constructor checking by epa
Parent article: Toward safe transmutation in Rust

This can also be done by giving the type another constructor or helper method that constructs an instance of the type by transmutation, right?

In this case the type would want to be able to mark itself as able to be transmuted to, but only when the type itself is doing the transmuting. Essentially a private access marker trait. I don't know enough Rust to know if this is possible.


to post comments

Constructor checking

Posted Oct 28, 2024 7:43 UTC (Mon) by NYKevin (subscriber, #129325) [Link]

In this case the type would want to be able to mark itself as able to be transmuted to, but only when the type itself is doing the transmuting.

You can sort of do that now:

// Simple one-field struct as an example, can be replaced with a more complicated struct.
#[repr(C)] // But it does need to be repr(C) or repr(transparent)
struct MyType(u64);

use std::convert::TryFrom;

impl<'a> TryFrom<&'a [u8]> for &'a MyType {
    type Error = &'static str;  // XXX: In a real codebase, use a proper Error type and not a string.
    fn try_from(x: &'a [u8]) -> Result<Self, &'static str> {
        if x.len() != std::mem::size_of::<MyType>() {
            return Err("Wrong size!");
        }
        let ptr: *const MyType = unsafe { std::mem::transmute(x.as_ptr()) };
        if ptr.is_aligned() {
            Ok(unsafe { &*ptr })
        } else {
            Err("Not aligned!")
        }
    }
}

// Implementation for &'a mut [u8] omitted because it's nearly identical.

// Now safe code can call try_from() and try_into() for this conversion.

But this is just a thin wrapper around transmute. It's sound, in this case, but if MyType is more complicated, then you have all the problems that the article describes. The compiler is not going to do very much for you here (the only check that the compiler performs in the above example code is to make sure that a pointer-to-u8 is the same size as a pointer-to-MyType, which is rather obvious anyway).

(If this looks like a lot of boilerplate code, bear in mind that Rust has macros, so you don't have to write all of this out repeatedly if you're doing it a lot.)


Copyright © 2024, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds