use crate::{
boxed::{ArchivedBox, BoxResolver},
ser::Serializer,
ArchivePointee, ArchiveUnsized, SerializeUnsized,
};
use core::{
cmp::{self, Eq, Ord, PartialEq, PartialOrd},
fmt, hash,
hint::unreachable_unchecked,
ops::Deref,
pin::Pin,
};
#[repr(transparent)]
pub struct ArchivedOptionBox<T: ArchivePointee + ?Sized> {
inner: ArchivedBox<T>,
}
impl<T: ArchivePointee + ?Sized> ArchivedOptionBox<T> {
#[inline]
pub fn is_none(&self) -> bool {
self.as_ref().is_none()
}
#[inline]
pub fn is_some(&self) -> bool {
self.as_ref().is_some()
}
#[inline]
pub fn as_ref(&self) -> Option<&ArchivedBox<T>> {
if self.inner.is_null() {
None
} else {
Some(&self.inner)
}
}
#[inline]
pub fn as_mut(&mut self) -> Option<&mut ArchivedBox<T>> {
if self.inner.is_null() {
None
} else {
Some(&mut self.inner)
}
}
#[inline]
pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&ArchivedBox<T>>> {
unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) }
}
#[inline]
pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut ArchivedBox<T>>> {
unsafe {
Pin::get_unchecked_mut(self)
.as_mut()
.map(|x| Pin::new_unchecked(x))
}
}
#[inline]
pub fn iter(&self) -> Iter<'_, ArchivedBox<T>> {
Iter {
inner: self.as_ref(),
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, ArchivedBox<T>> {
IterMut {
inner: self.as_mut(),
}
}
#[inline]
pub fn as_deref(&self) -> Option<&T> {
self.as_ref().map(|x| (*x).deref())
}
}
impl<T: ArchivePointee + ?Sized> ArchivedOptionBox<T>
where
T::ArchivedMetadata: Default,
{
#[inline]
pub unsafe fn resolve_from_option<U: ArchiveUnsized<Archived = T> + ?Sized>(
field: Option<&U>,
pos: usize,
resolver: OptionBoxResolver<U::MetadataResolver>,
out: *mut Self,
) {
let (fp, fo) = out_field!(out.inner);
if let Some(value) = field {
let resolver = if let OptionBoxResolver::Some(metadata_resolver) = resolver {
metadata_resolver
} else {
unreachable_unchecked();
};
ArchivedBox::resolve_from_ref(value, pos + fp, resolver, fo)
} else {
ArchivedBox::emplace_null(pos + fp, fo);
}
}
#[inline]
pub fn serialize_from_option<U, S>(
field: Option<&U>,
serializer: &mut S,
) -> Result<OptionBoxResolver<U::MetadataResolver>, S::Error>
where
U: SerializeUnsized<S, Archived = T> + ?Sized,
S: Serializer + ?Sized,
{
if let Some(value) = field {
Ok(OptionBoxResolver::Some(ArchivedBox::serialize_from_ref(
value, serializer,
)?))
} else {
Ok(OptionBoxResolver::None)
}
}
}
impl<T: ArchivePointee + ?Sized> fmt::Debug for ArchivedOptionBox<T>
where
T::ArchivedMetadata: fmt::Debug,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.as_ref() {
Some(inner) => inner.fmt(f),
None => f.debug_tuple("None").finish(),
}
}
}
impl<T: ArchivePointee + Eq + ?Sized> Eq for ArchivedOptionBox<T> {}
impl<T: ArchivePointee + hash::Hash + ?Sized> hash::Hash for ArchivedOptionBox<T> {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.as_ref().hash(state)
}
}
impl<T: ArchivePointee + Ord + ?Sized> Ord for ArchivedOptionBox<T> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_ref().cmp(&other.as_ref())
}
}
impl<T: ArchivePointee + PartialEq + ?Sized> PartialEq for ArchivedOptionBox<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_ref().eq(&other.as_ref())
}
}
impl<T: ArchivePointee + PartialOrd + ?Sized> PartialOrd for ArchivedOptionBox<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.as_ref().partial_cmp(&other.as_ref())
}
}
pub type Iter<'a, T> = crate::option::Iter<'a, T>;
pub type IterMut<'a, T> = crate::option::IterMut<'a, T>;
pub enum OptionBoxResolver<T> {
None,
Some(BoxResolver<T>),
}