object-rainbow 0.0.0-a.72

distributed object model
Documentation
use std::sync::Arc;

use crate::{extras::Extras, object_marker::ObjectMarker, *};

pub trait ExtractResolve: FetchBytes {
    fn extract_resolve<R: Any>(&self) -> Option<(&Address, &R)> {
        let AddressedBytes { address, resolve } =
            self.as_inner()?.downcast_ref::<AddressedBytes>()?;
        let resolve = resolve.as_ref().any_ref().downcast_ref::<R>()?;
        Some((address, resolve))
    }
}

impl<T: ?Sized + FetchBytes> ExtractResolve for T {}

#[derive(
    Clone, ToOutput, InlineOutput, Tagged, ListHashes, Parse, ParseInline, Size, MaybeHasNiche,
)]
pub struct AddressedBytes {
    pub address: Address,
    pub resolve: Arc<dyn Resolve>,
}

impl FetchBytes for AddressedBytes {
    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
        self.resolve.resolve(self.address, &self.resolve)
    }

    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
        self.resolve.resolve_data(self.address)
    }

    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
        self.resolve.try_resolve_local(self.address, &self.resolve)
    }

    fn as_resolve(&self) -> Option<&Arc<dyn Resolve>> {
        Some(&self.resolve)
    }

    fn try_unwrap_resolve(self: Arc<Self>) -> Option<Arc<dyn Resolve>> {
        Arc::try_unwrap(self)
            .ok()
            .map(|Self { resolve, .. }| resolve)
    }
}

impl Singular for AddressedBytes {
    fn hash(&self) -> Hash {
        self.address.hash
    }
}

impl<I: PointInput> Parse<I> for Arc<dyn '_ + Singular> {
    fn parse(input: I) -> crate::Result<Self> {
        Self::parse_as_inline(input)
    }
}

impl<I: PointInput> ParseInline<I> for Arc<dyn '_ + Singular> {
    fn parse_inline(input: &mut I) -> crate::Result<Self> {
        Ok(Arc::new(input.parse_inline::<AddressedBytes>()?))
    }
}

#[derive(
    ToOutput,
    InlineOutput,
    Tagged,
    ListHashes,
    Parse,
    ParseInline,
    Size,
    MaybeHasNiche,
    CanonicalExtra,
    ToCanonicalExtra,
)]
pub struct Addressed<T, Extra> {
    extra: Extras<Extra>,
    inner: AddressedBytes,
    _object: ObjectMarker<T>,
}

impl<T, Extra> AsRef<Extra> for Addressed<T, Extra> {
    fn as_ref(&self) -> &Extra {
        &self.extra
    }
}

impl<T: Traversible, Extra: 'static + Send + Sync + Clone + ExtraFor<T>> Topological
    for Addressed<T, Extra>
{
    fn traverse(&self, visitor: &mut (impl ?Sized + PointVisitor)) {
        visitor.visit(self);
    }
}

impl<T, Extra: Clone> Clone for Addressed<T, Extra> {
    fn clone(&self) -> Self {
        Self {
            extra: self.extra.clone(),
            inner: self.inner.clone(),
            _object: Default::default(),
        }
    }
}

impl<T, Extra> Addressed<T, Extra> {
    pub fn from_inner(inner: AddressedBytes, extra: Extra) -> Self {
        Self {
            extra: Extras(extra),
            inner,
            _object: Default::default(),
        }
    }
}

impl<T, Extra> FetchBytes for Addressed<T, Extra> {
    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
        self.inner.fetch_bytes()
    }

    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
        self.inner.fetch_data()
    }

    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
        self.inner.fetch_bytes_local()
    }

    fn as_inner(&self) -> Option<&dyn Any> {
        Some(&self.inner)
    }

    fn as_resolve(&self) -> Option<&Arc<dyn Resolve>> {
        self.inner.as_resolve()
    }

    fn try_unwrap_resolve(self: Arc<Self>) -> Option<Arc<dyn Resolve>> {
        Arc::try_unwrap(self)
            .ok()
            .map(|Self { inner, .. }| inner.resolve)
    }
}

impl<T, Extra: Send + Sync> Singular for Addressed<T, Extra> {
    fn hash(&self) -> Hash {
        self.inner.hash()
    }
}

impl<T: FullHash, Extra: Send + Sync + ExtraFor<T>> Fetch for Addressed<T, Extra> {
    type T = T;

    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
        self.fetch_checked()
    }

    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Self::T>> {
        self.try_fetch_local_checked()
    }
}

impl<'a, T: 'a + FullHash, I: PointInput<Extra: Send + Sync + ExtraFor<T>>> Parse<I>
    for Arc<dyn 'a + SingularFetch<T = T>>
{
    fn parse(input: I) -> crate::Result<Self> {
        Self::parse_as_inline(input)
    }
}

impl<'a, T: 'a + FullHash, I: PointInput<Extra: Send + Sync + ExtraFor<T>>> ParseInline<I>
    for Arc<dyn 'a + SingularFetch<T = T>>
{
    fn parse_inline(input: &mut I) -> crate::Result<Self> {
        Ok(Arc::new(input.parse_inline::<Addressed<_, _>>()?))
    }
}