Skip to content

Commit 85ed994

Browse files
joshlfjswrenn
authored andcommitted
Initial commit of DstLayout::for_dst
This will be used by the custom derive of `KnownLayout` to compute the `DstLayout` for unsized types. Makes progress on #29
1 parent 89ca5ab commit 85ed994

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

src/lib.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,52 @@ impl DstLayout {
427427
}
428428
}
429429

430+
/// Constructs a `DstLayout` which describes a dynamically-sized type with
431+
/// the given properties.
432+
///
433+
/// # Safety
434+
///
435+
/// Unsafe code may assume that the returned `DstLayout` is the correct
436+
/// layout for the described type so long as:
437+
/// - The type has the alignment `align`
438+
/// - The type has at least one field
439+
/// - The byte offset of the first byte of the trailing field is equal to
440+
/// `trailing_field_offset`
441+
/// - The trailing field's layout is correctly described by
442+
/// `trailing_field_layout`
443+
const fn for_dst(
444+
align: NonZeroUsize,
445+
trailing_field_offset: usize,
446+
trailing_field_layout: DstLayout,
447+
) -> Option<DstLayout> {
448+
Some(DstLayout {
449+
// SAFETY: The caller has promised that this is the correct
450+
// alignment.
451+
_align: align,
452+
_size_info: match trailing_field_layout._size_info {
453+
SizeInfo::Sized { _size } => {
454+
let without_padding = match trailing_field_offset.checked_add(_size) {
455+
Some(without_padding) => without_padding,
456+
None => return None,
457+
};
458+
459+
let padding = util::core_layout::_padding_needed_for(without_padding, align);
460+
// SAFETY: TODO
461+
SizeInfo::Sized { _size: without_padding + padding }
462+
}
463+
SizeInfo::SliceDst(TrailingSliceLayout { _offset, _elem_size }) => {
464+
let offset = match trailing_field_offset.checked_add(_offset) {
465+
Some(offset) => offset,
466+
None => return None,
467+
};
468+
469+
// SAFETY: TODO
470+
SizeInfo::SliceDst(TrailingSliceLayout { _offset: offset, _elem_size })
471+
}
472+
},
473+
})
474+
}
475+
430476
/// Validates that a cast is sound from a layout perspective.
431477
///
432478
/// Validates that the size and alignment requirements of a type with the
@@ -3684,6 +3730,20 @@ mod tests {
36843730
}
36853731
}
36863732

3733+
#[test]
3734+
fn test_dst_layout_for_dst() {
3735+
macro_rules! test {
3736+
($align:expr, $trailing_field_offset:expr, $trailing_field_layout:expr, $expect:expr) => {{
3737+
let align = NonZeroUsize::new($align).unwrap();
3738+
let layout =
3739+
DstLayout::for_dst(align, $trailing_field_offset, $trailing_field_layout);
3740+
assert_eq!(layout, $expect);
3741+
}};
3742+
}
3743+
3744+
// TODO: Write tests.
3745+
}
3746+
36873747
// This test takes a long time when running under Miri, so we skip it in
36883748
// that case. This is acceptable because this is a logic test that doesn't
36893749
// attempt to expose UB.

0 commit comments

Comments
 (0)