jswrenn / typic

Type-safe transmutations between layout-compatible types.
https://crates.io/crates/typic
Apache License 2.0
121 stars 4 forks source link

typic::repr(C) structs including other typic::repr(C) structs? #11

Open miquels opened 4 years ago

miquels commented 4 years ago

I'm trying to serialize a struct into a [u8; size] array that has a member that's also a struct. I've tried a lot of variations but nothing works. I this supposed to work? The below code gives this error:

error[E0277]: the trait bound `typic::private::bytelevel::slot::bytes::Bytes<typic::private::highlevel::field::Public, typic::private::bytelevel::slot::bytes::kind::Initialized, typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>>: typic::private::transmute::from_layout::bytes_to::BytesFromBytes<typic::private::bytelevel::slot::bytes::Bytes<typic::private::highlevel::field::Private, typic::private::bytelevel::slot::bytes::kind::Uninitialized, typenum::uint::UTerm>, typic::private::transmute::Variant, typic::private::transmute::Enforced, typic::private::transmute::AlwaysValid>` is not satisfied
  --> src/main.rs:26:9
   |
26 |     dhe.transmute_into()
   |         ^^^^^^^^^^^^^^ the trait `typic::private::transmute::from_layout::bytes_to::BytesFromBytes<typic::private::bytelevel::slot::bytes::Bytes<typic::private::highlevel::field::Private, typic::private::bytelevel::slot::bytes::kind::Uninitialized, typenum::uint::UTerm>, typic::private::transmute::Variant, typic::private::transmute::Enforced, typic::private::transmute::AlwaysValid>` is not implemented for `typic::private::bytelevel::slot::bytes::Bytes<typic::private::highlevel::field::Public, typic::private::bytelevel::slot::bytes::kind::Initialized, typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>>`
   |
   = help: the following implementations were found:
[lots more]

This is the code:

use std::default::Default;
use typic::{self, transmute::StableTransmuteInto, stability::StableABI};

#[typic::repr(C)]
#[derive(Clone, Debug, Default, PartialEq, StableABI)]
pub struct DHash {
    pub h1: u32,
    pub h2: u32,
}

#[typic::repr(C)]
#[derive(Debug, Default, StableABI)]
#[rustfmt::skip]
struct DHistEnt {
    next:       u32,        // link to next entry
    gmt:        u32,        // unixtime / 60
    hv:         DHash,      // hash
    iter:       u16,        // filename (B.04x)
    exp:        u16,        // see above
    boffset:    u32,        // article offset
    bsize:      u32,        // article size
}
const DHISTENT_SIZE: usize = 28;

fn dhe_to_u8(dhe: DHistEnt) -> [u8; DHISTENT_SIZE] {
    dhe.transmute_into()
}

fn main() {
    let dh = DHistEnt::default();
    let buf = dhe_to_u8(dh);

    println!("{:?}", buf);
}
jswrenn commented 4 years ago

That's definitely supposed to work! Typic's guts were recently in a bit of flux, and I'm not surprised I might have broken something. Thank you very much for filing the issue.

Judging from the error message, it seems like I might have an off-by-one error in the either the layout computation, or maybe when elements are chomped off the array Array, when compatibility is being checked. (Ugh!)