Skip to content

Commit 8348074

Browse files
authored
Merge pull request #188 from aldanor/feature/more-derive-reprs
2 parents 8195fce + 8877f38 commit 8348074

File tree

9 files changed

+103
-25
lines changed

9 files changed

+103
-25
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
- `Error` now implements `From<Infallible>`, which allows passing convertible
88
extents (like tuples of integers) where `impl TryInto<Extents>` is required.
99
- Support for HDF5 versions 1.12.1 and 1.10.8
10+
- `#[derive(H5Type)]` now supports structs / tuple structs with `repr(packed)`.
11+
- `#[derive(H5Type)]` now supports structs / tuple structs with
12+
`repr(transparent)` (the generated HDF5 type is equivalent to the type of
13+
the field and is not compound).
1014

1115
### Changed
1216

hdf5-derive/src/lib.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ where
6161
}
6262
}
6363

64+
fn impl_transparent(ty: &Type) -> TokenStream {
65+
quote! {
66+
<#ty as _h5::types::H5Type>::type_descriptor()
67+
}
68+
}
69+
6470
fn impl_enum(names: Vec<Ident>, values: Vec<Expr>, repr: &Ident) -> TokenStream {
6571
let size = Ident::new(
6672
&format!(
@@ -149,11 +155,18 @@ fn impl_trait(
149155
if fields.is_empty() {
150156
panic!("Cannot derive H5Type for empty structs");
151157
}
152-
find_repr(attrs, &["C"]).expect("H5Type requires #[repr(C)] for structs");
153-
let types = pluck(fields.iter(), |f| f.ty.clone());
154-
let fields = pluck(fields.iter(), |f| f.ident.clone().unwrap());
155-
let names = fields.iter().map(|f| f.to_string()).collect::<Vec<_>>();
156-
impl_compound(ty, ty_generics, &fields, &names, &types)
158+
if find_repr(attrs, &["C", "packed", "transparent"]).expect(
159+
"H5Type requires repr(C), repr(packed) or repr(transparent) for structs",
160+
) == "transparent"
161+
{
162+
assert_eq!(fields.len(), 1);
163+
impl_transparent(&fields[0].ty)
164+
} else {
165+
let types = pluck(fields.iter(), |f| f.ty.clone());
166+
let fields = pluck(fields.iter(), |f| f.ident.clone().unwrap());
167+
let names = fields.iter().map(|f| f.to_string()).collect::<Vec<_>>();
168+
impl_compound(ty, ty_generics, &fields, &names, &types)
169+
}
157170
}
158171
Fields::Unnamed(ref fields) => {
159172
let (index, fields): (Vec<Index>, Vec<_>) = fields
@@ -166,10 +179,17 @@ fn impl_trait(
166179
if fields.is_empty() {
167180
panic!("Cannot derive H5Type for empty tuple structs");
168181
}
169-
find_repr(attrs, &["C"]).expect("H5Type requires #[repr(C)] for structs");
170-
let names = (0..fields.len()).map(|f| f.to_string()).collect::<Vec<_>>();
171-
let types = pluck(fields.iter(), |f| f.ty.clone());
172-
impl_compound(ty, ty_generics, &index, &names, &types)
182+
if find_repr(attrs, &["C", "packed", "transparent"]).expect(
183+
"H5Type requires repr(C), repr(packed) or repr(transparent) for tuple structs",
184+
) == "transparent"
185+
{
186+
assert_eq!(fields.len(), 1);
187+
impl_transparent(&fields[0].ty)
188+
} else {
189+
let names = (0..fields.len()).map(|f| f.to_string()).collect::<Vec<_>>();
190+
let types = pluck(fields.iter(), |f| f.ty.clone());
191+
impl_compound(ty, ty_generics, &index, &names, &types)
192+
}
173193
}
174194
},
175195
Data::Enum(ref data) => {

hdf5-derive/tests/compile-fail/struct-c-repr.stderr

Lines changed: 0 additions & 7 deletions
This file was deleted.

hdf5-derive/tests/compile-fail/struct-c-repr.rs renamed to hdf5-derive/tests/compile-fail/struct-no-repr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use hdf5_derive::H5Type;
33

44
#[derive(H5Type)]
55
//~^ ERROR proc-macro derive
6-
//~^^ HELP H5Type requires #[repr(C)] for structs
6+
//~^^ HELP H5Type requires repr(C), repr(packed) or repr(transparent) for structs
77
struct Foo {
88
bar: i64,
99
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
error: proc-macro derive panicked
2+
--> $DIR/struct-no-repr.rs:4:10
3+
|
4+
4 | #[derive(H5Type)]
5+
| ^^^^^^
6+
|
7+
= help: message: H5Type requires repr(C), repr(packed) or repr(transparent) for structs

hdf5-derive/tests/compile-fail/tuple-struct-c-repr.stderr

Lines changed: 0 additions & 7 deletions
This file was deleted.

hdf5-derive/tests/compile-fail/tuple-struct-c-repr.rs renamed to hdf5-derive/tests/compile-fail/tuple-struct-no-repr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use hdf5_derive::H5Type;
33

44
#[derive(H5Type)]
55
//~^ ERROR proc-macro derive
6-
//~^^ HELP H5Type requires #[repr(C)] for structs
6+
//~^^ HELP H5Type requires repr(C), repr(packed) or repr(transparent) for tuple structs
77
struct Foo(i64);
88

99
fn main() {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
error: proc-macro derive panicked
2+
--> $DIR/tuple-struct-no-repr.rs:4:10
3+
|
4+
4 | #[derive(H5Type)]
5+
| ^^^^^^
6+
|
7+
= help: message: H5Type requires repr(C), repr(packed) or repr(transparent) for tuple structs

hdf5-derive/tests/test.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// due to compiler wrongfully complaining re: Copy impl missing for packed struct
2+
#![allow(unaligned_references)]
3+
14
#[macro_use]
25
extern crate hdf5_derive;
36

@@ -30,6 +33,57 @@ struct B {
3033
#[repr(C)]
3134
struct T(i64, pub u64);
3235

36+
#[derive(H5Type, Copy, Clone)]
37+
#[repr(packed)]
38+
struct P1 {
39+
x: u8,
40+
y: u64,
41+
}
42+
43+
#[derive(H5Type, Copy, Clone)]
44+
#[repr(packed)]
45+
struct P2(i8, u32);
46+
47+
#[derive(H5Type)]
48+
#[repr(transparent)]
49+
struct T1 {
50+
_x: u64,
51+
}
52+
53+
#[derive(H5Type)]
54+
#[repr(transparent)]
55+
struct T2(i32);
56+
57+
#[test]
58+
fn test_compound_packed() {
59+
assert_eq!(
60+
P1::type_descriptor(),
61+
TD::Compound(CompoundType {
62+
fields: vec![
63+
CompoundField::typed::<u8>("x", 0, 0),
64+
CompoundField::typed::<u64>("y", 1, 1),
65+
],
66+
size: 9,
67+
})
68+
);
69+
assert_eq!(
70+
P2::type_descriptor(),
71+
TD::Compound(CompoundType {
72+
fields: vec![
73+
CompoundField::typed::<i8>("0", 0, 0),
74+
CompoundField::typed::<u32>("1", 1, 1),
75+
],
76+
size: 5,
77+
})
78+
);
79+
}
80+
81+
#[test]
82+
fn test_compound_transparent() {
83+
assert_eq!(T1::type_descriptor(), u64::type_descriptor(),);
84+
assert_eq!(T2::type_descriptor(), i32::type_descriptor(),);
85+
}
86+
3387
#[test]
3488
fn test_compound_simple() {
3589
assert_eq!(

0 commit comments

Comments
 (0)