use crate::{
attachment::{
raw::{RawAttachmentMut, RawAttachmentRef},
vtable::AttachmentVtable,
},
handlers::AttachmentHandler,
};
#[repr(C)]
pub(crate) struct AttachmentData<A: 'static> {
vtable: &'static AttachmentVtable,
attachment: A,
}
impl<A: 'static> AttachmentData<A> {
#[inline]
pub(super) fn new<H: AttachmentHandler<A>>(attachment: A) -> Self {
Self {
vtable: AttachmentVtable::new::<A, H>(),
attachment,
}
}
}
impl<'a> RawAttachmentRef<'a> {
#[inline]
pub(super) fn vtable(self) -> &'static AttachmentVtable {
let ptr = self.as_ptr();
let vtable_ptr: *const &'static AttachmentVtable = unsafe {
&raw const (*ptr).vtable
};
unsafe { *vtable_ptr }
}
#[inline]
pub unsafe fn attachment_downcast_unchecked<A: 'static>(self) -> &'a A {
let this = unsafe {
self.cast_inner::<A>()
};
&this.attachment
}
}
impl<'a> RawAttachmentMut<'a> {
#[inline]
pub unsafe fn into_attachment_downcast_unchecked<A: 'static>(self) -> &'a mut A {
let this = unsafe {
self.cast_inner::<A>()
};
&mut this.attachment
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_attachment_field_offsets() {
use core::mem::{offset_of, size_of};
#[repr(align(32))]
struct LargeAlignment {
_value: u8,
}
assert_eq!(offset_of!(AttachmentData<u8>, vtable), 0);
assert_eq!(offset_of!(AttachmentData<u32>, vtable), 0);
assert_eq!(offset_of!(AttachmentData<[u64; 4]>, vtable), 0);
assert_eq!(offset_of!(AttachmentData<LargeAlignment>, vtable), 0);
assert!(
offset_of!(AttachmentData<u8>, attachment) >= size_of::<&'static AttachmentVtable>()
);
assert!(
offset_of!(AttachmentData<u32>, attachment) >= size_of::<&'static AttachmentVtable>()
);
assert!(
offset_of!(AttachmentData<[u64; 4]>, attachment)
>= size_of::<&'static AttachmentVtable>()
);
assert!(
offset_of!(AttachmentData<LargeAlignment>, attachment)
>= size_of::<&'static AttachmentVtable>()
);
}
}