sark-http 0.26.2

HTTP wire types, semantics, codecs, and ownership invariants for Sark
Documentation
use std::{borrow::Borrow, convert::Infallible, ptr};

use o3::buffer::{
    self, hold, resident, segments,
    storage::{self, backing},
};

use crate::{
    owner::handoff::stage,
    payload::{owned, response::Body as _},
    request::body,
};

#[derive(Clone, Copy, Debug)]
pub enum Retained<'req, 'd> {
    Segments(&'req owned::Segments<'d>),
    Resident(&'req resident::Shared<'d>),
    Shared(&'req storage::Shared),
}

impl<'req, 'd> Retained<'req, 'd> {
    pub(crate) fn count(self) -> segments::Count {
        match self {
            Self::Segments(owner) => owner.count(),
            Self::Resident(owner) => segments::Count::new(u32::from(!owner.is_empty())),
            Self::Shared(owner) => segments::Count::new(u32::from(!owner.is_empty())),
        }
    }

    pub(crate) fn segment(self, index: usize) -> Option<&'req [u8]> {
        match self {
            Self::Segments(owner) => owner.segment(index),
            Self::Resident(owner) => (index == 0 && !owner.is_empty()).then(|| owner.as_slice()),
            Self::Shared(owner) => (index == 0 && !owner.is_empty()).then(|| owner.as_ref()),
        }
    }

    pub(crate) fn as_slice(&self) -> Option<&'req [u8]> {
        match *self {
            Self::Segments(owner) => owner.as_slice(),
            Self::Resident(owner) => Some(owner.as_slice()),
            Self::Shared(owner) => Some(owner.as_ref()),
        }
    }

    pub(crate) fn contiguous(self) -> Option<body::View<'req, 'd>> {
        match self {
            Self::Segments(owner) => match owner.storage() {
                segments::Shape::Empty => Some(body::View::Slice(&[])),
                segments::Shape::One(owner) => Some(body::View::Resident(owner.as_ref())),
                segments::Shape::Many(_) => None,
            },
            Self::Resident(owner) => Some(body::View::Resident(owner)),
            Self::Shared(owner) => Some(body::View::Shared(owner)),
        }
    }

    pub(crate) fn is_same(self, other: Self) -> bool {
        match (self, other) {
            (Self::Segments(left), Self::Segments(right)) => ptr::eq(left, right),
            (Self::Resident(left), Self::Resident(right)) => ptr::eq(left, right),
            (Self::Shared(left), Self::Shared(right)) => ptr::eq(left, right),
            _ => false,
        }
    }

    pub(crate) fn charge(self) -> hold::Charge {
        match self {
            Self::Segments(owner) => owner.charge(),
            Self::Resident(owner) => owner
                .backing()
                .map_or_else(hold::Charge::default, |backing| {
                    hold::Charge::from_owner(owner.len(), backing.resident())
                }),
            Self::Shared(owner) => owner
                .backing()
                .map_or_else(hold::Charge::default, |backing| {
                    hold::Charge::from_owner(owner.len(), backing.resident())
                }),
        }
    }

    pub(crate) fn contains(self, response: backing::View<'_, '_>) -> bool {
        match self {
            Self::Segments(owner) => owner.backings().any(|backing| backing.contains(&response)),
            Self::Resident(owner) => owner
                .backing()
                .is_some_and(|backing| backing.contains(&response)),
            Self::Shared(owner) => owner
                .backing()
                .is_some_and(|backing| backing.contains(&response)),
        }
    }

    pub(crate) fn try_clone(self) -> Result<owned::Segments<'d>, owned::Error> {
        match self {
            Self::Segments(owner) => owner.try_clone(),
            Self::Resident(owner) => owner
                .try_clone()
                .map(owned::Segments::from)
                .map_err(owned::Error::Retain),
            Self::Shared(owner) => owner
                .try_clone()
                .map(owned::Segments::from)
                .map_err(owned::Error::Retain),
        }
    }

    pub(crate) fn try_slice(
        self,
        bytes: &[u8],
    ) -> Result<Option<owned::Segments<'d>>, owned::Error> {
        match self {
            Self::Segments(owner) => {
                let select =
                    |owner: &'req resident::Shared<'d>| buffer::View::new(owner).select(bytes);
                let view = match owner.storage() {
                    segments::Shape::Empty => None,
                    segments::Shape::One(owner) => select(owner),
                    segments::Shape::Many(owners) => owners.as_chain().segments().find_map(select),
                };
                view.map(|view| {
                    view.try_retain()
                        .map(owned::Segments::from)
                        .map_err(owned::Error::Retain)
                })
                .transpose()
            }
            Self::Resident(owner) => buffer::View::new(owner)
                .select(bytes)
                .map(|view| {
                    view.try_retain()
                        .map(owned::Segments::from)
                        .map_err(owned::Error::Retain)
                })
                .transpose(),
            Self::Shared(owner) => buffer::View::new(owner)
                .select(bytes)
                .map(|view| {
                    view.try_retain()
                        .map(owned::Segments::from)
                        .map_err(owned::Error::Retain)
                })
                .transpose(),
        }
    }
}

const _: () = assert!(size_of::<Retained<'static, 'static>>() == 2 * size_of::<usize>());

impl<'req, 'd: 'req> stage::Body<'req, 'd> for Retained<'req, 'd> {
    type Deferred = usize;

    fn defer(self) -> usize {
        match self {
            Self::Segments(owner) => owner.len(),
            Self::Resident(owner) => owner.len(),
            Self::Shared(owner) => owner.len(),
        }
    }
}
impl<'req, 'd: 'req> Borrow<Retained<'req, 'd>> for Infallible {
    fn borrow(&self) -> &Retained<'req, 'd> {
        match *self {}
    }
}