use std::any::type_name;
use std::mem::{MaybeUninit, offset_of};
use std::ptr::Alignment;
use crate::result::ArchivedResult;
use crate::util::max_alignment;
use crate::{Serialize, SerializeError, VerifyError};
impl<T: Serialize, U: Serialize> Serialize for Result<T, U> {
type Archived = ArchivedResult<T::Archived, U::Archived>;
const ALIGN: Alignment = max_alignment([T::ALIGN, U::ALIGN]);
const COPY_OPTIMIZATION: bool = T::COPY_OPTIMIZATION
&& U::COPY_OPTIMIZATION
&& offset_of!(Result<T, U>, Ok.0)
== offset_of!(ArchivedResult<T::Archived, U::Archived>, Ok.0)
&& offset_of!(Result<T, U>, Err.0)
== offset_of!(ArchivedResult<T::Archived, U::Archived>, Err.0);
unsafe fn serialize(
&self,
out: *mut MaybeUninit<ArchivedResult<T::Archived, U::Archived>>,
heap: *mut MaybeUninit<u8>,
) -> usize {
unsafe {
let (discriminant, size) = match self {
Ok(value) => (
0,
value.serialize(
out.cast::<u8>()
.add(offset_of!(ArchivedResult<T::Archived, U::Archived>, Ok.0))
.cast(),
heap,
),
),
Err(error) => (
1,
error.serialize(
out.cast::<u8>()
.add(offset_of!(ArchivedResult<T::Archived, U::Archived>, Err.0))
.cast(),
heap,
),
),
};
*out.cast() = discriminant;
size
}
}
fn serialized_size(&self, offset: usize) -> Result<usize, SerializeError> {
match self {
Ok(value) => value.serialized_size(offset),
Err(error) => error.serialized_size(offset),
}
}
#[inline]
unsafe fn verify(
this: *const ArchivedResult<T::Archived, U::Archived>,
buffer_end: *const u8,
) -> Result<(), VerifyError> {
unsafe {
let tag = *this.cast::<u8>();
match tag {
0 => T::verify(
this.cast::<u8>()
.add(offset_of!(ArchivedResult<T::Archived, U::Archived>, Ok.0))
.cast(),
buffer_end,
),
1 => U::verify(
this.cast::<u8>()
.add(offset_of!(ArchivedResult<T::Archived, U::Archived>, Err.0))
.cast(),
buffer_end,
),
_ => Err(VerifyError::InvalidEnumDiscriminantError {
enum_name: type_name::<ArchivedResult<T::Archived, U::Archived>>(),
invalid_discriminant: tag,
}),
}
}
}
}
#[cfg(test)]
mod tests {
use crate::test::roundtrip;
#[test]
fn roundtrip_result() {
roundtrip(&Result::<i32, u32>::Ok(12345i32));
roundtrip(&Result::<i32, u32>::Err(12345u32));
}
}