use std::any::type_name;
use std::mem::{MaybeUninit, offset_of};
use std::ptr::Alignment;
use crate::option::ArchivedOption;
use crate::{Serialize, SerializeError, VerifyError};
impl<T: Serialize> Serialize for Option<T> {
type Archived = ArchivedOption<T::Archived>;
const ALIGN: Alignment = T::ALIGN;
const COPY_OPTIMIZATION: bool = T::COPY_OPTIMIZATION
&& offset_of!(Option<T>, Some.0) == offset_of!(ArchivedOption<T::Archived>, Some.0);
unsafe fn serialize(
&self,
out: *mut MaybeUninit<ArchivedOption<T::Archived>>,
heap: *mut MaybeUninit<u8>,
) -> usize {
unsafe {
if let Some(val) = self {
*out.cast::<u8>() = 1;
val.serialize(
out.cast::<u8>()
.add(offset_of!(ArchivedOption<T::Archived>, Some.0))
.cast(),
heap,
)
} else {
*out = MaybeUninit::new(ArchivedOption::None);
0
}
}
}
fn serialized_size(&self, offset: usize) -> Result<usize, SerializeError> {
if let Some(val) = self {
val.serialized_size(offset)
} else {
Ok(0)
}
}
#[inline]
unsafe fn verify(
this: *const ArchivedOption<T::Archived>,
buffer_end: *const u8,
) -> Result<(), VerifyError> {
unsafe {
let tag = *this.cast::<u8>();
match tag {
0 => Ok(()),
1 => T::verify(
this.cast::<u8>()
.add(offset_of!(ArchivedOption<T::Archived>, Some.0))
.cast(),
buffer_end,
),
_ => Err(VerifyError::InvalidEnumDiscriminantError {
enum_name: type_name::<Option<T>>(),
invalid_discriminant: tag,
}),
}
}
}
}
#[cfg(test)]
mod tests {
use crate::test::roundtrip;
#[test]
fn roundtrip_option() {
roundtrip(&Option::<()>::None);
roundtrip(&Some(42));
}
}