capnproto-rust icon indicating copy to clipboard operation
capnproto-rust copied to clipboard

HasStructSize::struct_size() -> HasStructSize::STRUCT_SIZE

Open dwrensha opened this issue 3 years ago • 3 comments

HasStructSize::struct_size() was added at a time when Rust did not yet have associated constants. Converting it from a method to a constant makes it available for usage at compile time.

dwrensha avatar Apr 11 '21 13:04 dwrensha

Thanks, looks good from my side 👍.

schreter avatar Apr 11 '21 17:04 schreter

This is maybe not as useful as I had hoped. See https://github.com/rust-lang/rust/issues/45447

dwrensha avatar Apr 17 '21 23:04 dwrensha

No, unfortunately the associated constant is not that useful in the current state of affairs, but the desired functionality (creating an appropriately-sized array where to place the builder's buffer for simple in-place messages) can be achieved by creating a trait which defines an array type for the buffer. An example is in Rust Playground here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c8fe8990babd025d0419449d09ec421e or plaintext here:

mod _private {
    pub const SIZE: usize = 4;
}

trait IsInPlaceCapable {
    type StorageType : Sized + Default;
}

struct Reader {}
struct Builder {}

impl IsInPlaceCapable for Reader {
    type StorageType = [u64; _private::SIZE];
}
impl IsInPlaceCapable for Builder {
    type StorageType = [u64; _private::SIZE];
}

struct Wrapper<T: IsInPlaceCapable> 
{
    array: <T as IsInPlaceCapable>::StorageType
}

impl<T: IsInPlaceCapable> Wrapper<T> {
    fn new() -> Self {
        Self {
            array: <T as IsInPlaceCapable>::StorageType::default()
        }
    }
    
    fn print_size(&self) {
        println!("{}", std::mem::size_of::<Self>());
    }
}

fn main() {
    let x = Wrapper::<Reader>::new();
    x.print_size();
}

schreter avatar Apr 18 '21 11:04 schreter

Merging for inclusion in 0.15.0, which I intend to release after Rust 1.65 comes out next week.

dwrensha avatar Oct 29 '22 20:10 dwrensha

With this change, the _private::struct_size constant goes away. I checked that your example still works using an associated constant, as you will now need to do:

trait HasSize {
    const SIZE: usize;
}

trait IsInPlaceCapable {
    type StorageType : Sized + Default;
}

struct Reader {}

impl HasSize for Reader {
    const SIZE: usize = 4;    
}

struct Builder {}

impl HasSize for Builder {
    const SIZE: usize = 4;
}

impl IsInPlaceCapable for Reader {
    type StorageType = [u64; Reader::SIZE];
}
impl IsInPlaceCapable for Builder {
    type StorageType = [u64; Builder::SIZE];
}

struct Wrapper<T: IsInPlaceCapable> 
{
    array: <T as IsInPlaceCapable>::StorageType
}

impl<T: IsInPlaceCapable> Wrapper<T> {
    fn new() -> Self {
        Self {
            array: <T as IsInPlaceCapable>::StorageType::default()
        }
    }
    
    fn print_size(&self) {
        println!("{}", std::mem::size_of::<Self>());
    }
}

fn main() {
    let x = Wrapper::<Reader>::new();
    x.print_size();
}

dwrensha avatar Oct 29 '22 20:10 dwrensha

With this change, the _private::struct_size constant goes away.

Thanks. It is no problem to use the associated constant instead in our project.

schreter avatar Nov 05 '22 17:11 schreter