use std::{
cell::OnceCell,
fmt,
marker::PhantomData,
ops::{Deref, DerefMut},
rc::Rc,
};
use downcast_rs::{impl_downcast, Downcast};
use elsa::FrozenIndexMap;
use http::{HeaderMap, HeaderName, HeaderValue};
use smallvec::SmallVec;
use crate::{
convert::{Borrowable, ToHeaderName, ToHeaderValue},
handle::{RequestHandle, ResponseHandle},
};
use super::{INITIAL_HEADER_NAME_BUF_SIZE, INITIAL_HEADER_VALUE_BUF_SIZE};
pub(crate) struct LazyHandle<H: HandleWithHeaders> {
handle: OnceCell<H>,
headers: FrozenIndexMap<Rc<HeaderName>, Rc<LazyHeaderValues>>,
lazy_fields: LazyFields<H>,
}
impl<H: HandleWithHeaders> LazyHandle<H> {
pub fn detached() -> LazyHandleBuilder<Detached, H> {
LazyHandleBuilder {
lazy_handle: LazyHandle {
handle: OnceCell::new(),
lazy_fields: LazyFields::new(),
headers: FrozenIndexMap::new(),
},
_phantom: PhantomData,
}
}
pub fn from_handle(handle: H) -> LazyHandleBuilder<Attached, H> {
LazyHandleBuilder {
lazy_handle: LazyHandle {
handle: OnceCell::from(handle),
lazy_fields: LazyFields::new(),
headers: FrozenIndexMap::new(),
},
_phantom: PhantomData,
}
}
fn ensure_fully_loaded(&self) {
if let Some(handle) = self.handle.get() {
for name in handle.get_header_names() {
self.get_or_insert_header(name).values(Some(handle));
}
self.lazy_fields.init_all(handle);
}
}
fn flush_to_new_handle(&self) -> H {
self.ensure_fully_loaded();
let mut handle = H::new();
self.lazy_fields.flush_all(&mut handle);
for (name, value) in self.iter() {
handle.append_header(name, value)
}
handle
}
pub fn get_handle(&self) -> &H {
self.handle.get_or_init(|| self.flush_to_new_handle())
}
pub fn take_handle(&mut self) -> H {
self.ensure_fully_loaded();
if let Some(handle) = self.handle.take() {
handle
} else {
self.flush_to_new_handle()
}
}
pub fn into_handle(mut self) -> H {
self.handle
.take()
.unwrap_or_else(|| self.flush_to_new_handle())
}
pub fn get_field<T: HandleField<H>>(&self) -> &T {
self.lazy_fields.get_field::<T>(self.handle.get())
}
pub fn get_field_mut<T: HandleField<H>>(&mut self) -> impl DerefMut<Target = T> + '_ {
self.lazy_fields.get_field_mut::<T>(self.handle.get_mut())
}
pub fn put_field<T: HandleField<H>>(&mut self, val: T) {
self.lazy_fields.put_field(self.handle.get_mut(), val);
}
fn is_attached(&self) -> bool {
self.handle.get().is_some()
}
fn get_or_insert_header(&self, name: impl ToHeaderName) -> &LazyHeaderValues {
let name = name.into_borrowable();
let is_attached = self.is_attached();
self.headers.get(name.as_ref()).unwrap_or_else(move || {
let name = Rc::new(name.into_owned());
self.headers.insert(
name.clone(),
Rc::new(LazyHeaderValues::new(name, is_attached)),
)
})
}
fn get_or_insert_header_mut(
&mut self,
name: impl ToHeaderName,
) -> (Option<&mut H>, &mut LazyHeaderValues) {
let is_attached = self.is_attached();
let values = self
.headers
.as_mut()
.entry(Rc::new(name.into_owned()))
.or_insert_with_key(|name| Rc::new(LazyHeaderValues::new(name.clone(), is_attached)))
.make_mut();
(self.handle.get_mut(), values)
}
pub fn get_header_names(&self) -> impl Iterator<Item = &HeaderName> + '_ {
struct NamesIter<'a, I, H: HandleWithHeaders> {
map: &'a LazyHandle<H>,
state: NamesIterState<I>,
}
enum NamesIterState<I> {
IterFromHandle(I),
IterFromGuest(usize),
}
impl<'a, I: Iterator<Item = HeaderName>, H: HandleWithHeaders> Iterator for NamesIter<'a, I, H> {
type Item = &'a HeaderName;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.state {
NamesIterState::IterFromHandle(iter) => {
Some(self.map.get_or_insert_header(iter.next()?).name())
}
NamesIterState::IterFromGuest(i) => {
let name = self.map.headers.get_index(*i)?.1.name();
*i += 1;
Some(name)
}
}
}
}
let state = if let Some(handle) = self.handle.get() {
NamesIterState::IterFromHandle(handle.get_header_names())
} else {
NamesIterState::IterFromGuest(0)
};
NamesIter { map: self, state }
}
pub fn get_header_values(&self, name: impl ToHeaderName) -> &[HeaderValue] {
self.get_or_insert_header(name).values(self.handle.get())
}
pub fn set_header(&mut self, name: HeaderName, value: HeaderValue) {
let (handle, values) = self.get_or_insert_header_mut(name);
values.set_to_single(handle, value);
}
pub fn append_header_value(&mut self, name: &HeaderName, value: impl ToHeaderValue) {
let (handle, values) = self.get_or_insert_header_mut(name);
values.push(handle, value);
}
pub fn append_header_value_with_comma(&mut self, name: &HeaderName, value: impl ToHeaderValue) {
let old_values = self.get_header_values(name);
if let [v] = old_values {
let mut new_bytes = bytes::BytesMut::from(v.as_bytes());
new_bytes.extend_from_slice(b", ");
new_bytes.extend_from_slice(value.into_owned().as_bytes());
self.set_header(
name.clone(),
HeaderValue::from_maybe_shared(new_bytes.freeze())
.expect("appending two valid headers should produce a valid header"),
);
} else {
self.append_header_value(name, value)
}
}
pub fn remove_header(&mut self, name: &HeaderName) -> Option<HeaderValue> {
let header_val = self
.headers
.as_mut()
.swap_remove(name)
.map(|v| v.first_as_owned(self.handle.get()))
.unwrap_or_else(|| {
self.handle
.get()
.and_then(|handle| handle.get_header_values(name).next())
});
if let Some(handle) = self.handle.get_mut() {
if header_val.is_some() {
handle.remove_header(name);
}
}
header_val
}
pub fn iter(&self) -> impl Iterator<Item = (&HeaderName, &HeaderValue)> {
self.get_header_names().flat_map(|name| {
self.get_header_values(name)
.iter()
.map(move |val| (name, val))
})
}
}
pub(crate) trait HandleField<H: HandleWithHeaders>: 'static + Clone {
fn load(handle: &H) -> Self;
fn store(&self, handle: &mut H);
}
trait LazyField<H>: Downcast {
fn ensure_init(&self, handle: &H);
fn flush(&self, handle: &mut H);
fn clone_object(&self) -> Rc<dyn LazyField<H>>;
}
impl_downcast!(LazyField<H>);
impl<H: HandleWithHeaders, T: HandleField<H>> LazyField<H> for OnceCell<T> {
fn ensure_init(&self, handle: &H) {
self.get_or_init(|| T::load(handle));
}
fn flush(&self, handle: &mut H) {
T::store(
self.get()
.expect("flush is only called for detached fields"),
handle,
)
}
fn clone_object(&self) -> Rc<dyn LazyField<H>> {
Rc::new(self.clone())
}
}
struct LazyFieldMutGuard<'a, T: HandleField<H>, H: HandleWithHeaders> {
handle: Option<&'a mut H>,
field: &'a mut OnceCell<T>,
}
impl<T: HandleField<H>, H: HandleWithHeaders> Deref for LazyFieldMutGuard<'_, T, H> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.field.get_or_init(|| {
T::load(
self.handle
.as_ref()
.expect("handle is present if lazy field is unitialized"),
)
})
}
}
impl<T: HandleField<H>, H: HandleWithHeaders> DerefMut for LazyFieldMutGuard<'_, T, H> {
fn deref_mut(&mut self) -> &mut Self::Target {
if let Some(handle) = &self.handle {
self.field.ensure_init(handle);
}
self.field.get_mut().expect("field is initialized")
}
}
impl<T: HandleField<H>, H: HandleWithHeaders> Drop for LazyFieldMutGuard<'_, T, H> {
fn drop(&mut self) {
if let Some(handle) = self.handle.take() {
self.field.flush(handle)
}
}
}
struct LazyFields<H: HandleWithHeaders> {
fields: Vec<Rc<dyn LazyField<H>>>,
}
impl<H: HandleWithHeaders> LazyFields<H> {
fn new() -> Self {
Self { fields: Vec::new() }
}
fn add_field<T: HandleField<H>>(&mut self, val: T) {
let field: OnceCell<T> = OnceCell::from(val);
self.fields.push(Rc::new(field));
}
fn add_field_lazy<T: HandleField<H>>(&mut self) {
let field: OnceCell<T> = OnceCell::new();
self.fields.push(Rc::new(field));
}
fn get_field<T: HandleField<H>>(&self, handle: Option<&H>) -> &T {
self.fields
.iter()
.find_map(|f| f.downcast_ref::<OnceCell<T>>())
.expect("field is present")
.get_or_init(|| {
T::load(handle.expect("handle is present if lazy field is unitialized"))
})
}
fn get_field_mut<'a, T: HandleField<H>>(
&'a mut self,
handle: Option<&'a mut H>,
) -> impl DerefMut<Target = T> + 'a {
let field_mut_rc = self
.fields
.iter_mut()
.find(|f| f.is::<OnceCell<T>>())
.expect("field is present");
if Rc::strong_count(field_mut_rc) > 1 {
*field_mut_rc = field_mut_rc.clone_object();
}
let field = Rc::get_mut(field_mut_rc)
.expect("field_mut_rc is unique")
.downcast_mut::<OnceCell<T>>()
.expect("field was already typechecked");
LazyFieldMutGuard { field, handle }
}
fn put_field<T: HandleField<H>>(&mut self, handle: Option<&mut H>, val: T) {
if let Some(handle) = handle {
T::store(&val, handle)
}
let field = self
.fields
.iter_mut()
.find(|f| f.is::<OnceCell<T>>())
.expect("field is present");
*field = Rc::new(OnceCell::from(val));
}
fn init_all(&self, handle: &H) {
for field in &self.fields {
field.ensure_init(handle)
}
}
fn flush_all(&self, handle: &mut H) {
for field in &self.fields {
field.flush(handle)
}
}
}
impl<H: HandleWithHeaders> Clone for LazyFields<H> {
fn clone(&self) -> Self {
Self {
fields: self.fields.iter().map(|f| f.clone_object()).collect(),
}
}
}
pub(crate) struct Attached;
pub(crate) struct Detached;
pub(crate) struct LazyHandleBuilder<T, H: HandleWithHeaders> {
lazy_handle: LazyHandle<H>,
_phantom: PhantomData<T>,
}
impl<H: HandleWithHeaders> LazyHandleBuilder<Attached, H> {
pub fn with_field_lazy<T: HandleField<H>>(mut self) -> Self {
self.lazy_handle.lazy_fields.add_field_lazy::<T>();
self
}
}
impl<H: HandleWithHeaders> LazyHandleBuilder<Detached, H> {
pub fn with_headers(mut self, input_map: HeaderMap) -> Self {
let headers = FrozenIndexMap::new();
let mut iter = input_map.into_iter().peekable();
while let Some((Some(name), first_val)) = iter.next() {
let name = Rc::new(name);
let mut values = LazyHeaderValues::from_value(name.clone(), first_val);
while matches!(iter.peek(), Some((None, _))) {
let Some((None, val)) = iter.next() else {
panic!("Bug in peekable iterator")
};
values.push(None::<&mut H>, val)
}
headers.insert(name, Rc::new(values));
}
self.lazy_handle.headers = headers;
self
}
}
impl<A, H: HandleWithHeaders> LazyHandleBuilder<A, H> {
pub fn with_field<T: HandleField<H>>(mut self, val: T) -> Self {
self.lazy_handle.lazy_fields.add_field(val);
self
}
pub fn finish(self) -> LazyHandle<H> {
self.lazy_handle
}
}
impl<H: HandleWithHeaders> Clone for LazyHandle<H> {
fn clone(&self) -> Self {
self.ensure_fully_loaded();
Self {
headers: self.headers.clone(),
handle: OnceCell::new(),
lazy_fields: self.lazy_fields.clone(),
}
}
}
#[derive(Clone)]
struct LazyHeaderValues {
name: Rc<HeaderName>,
values: OnceCell<SmallVec<[HeaderValue; 1]>>,
}
impl LazyHeaderValues {
fn new(name: Rc<HeaderName>, is_attached: bool) -> Self {
Self {
name,
values: if is_attached {
OnceCell::new()
} else {
OnceCell::from(SmallVec::new())
},
}
}
fn from_value(name: Rc<HeaderName>, value: HeaderValue) -> Self {
Self {
name,
values: OnceCell::from(SmallVec::from_elem(value, 1)),
}
}
fn make_mut(self: &mut Rc<Self>) -> &mut Self {
Rc::make_mut(self)
}
fn make_owned(self: Rc<Self>) -> Self {
Rc::unwrap_or_clone(self)
}
fn name(&self) -> &HeaderName {
&self.name
}
fn values(&self, handle: Option<&impl HandleWithHeaders>) -> &[HeaderValue] {
self.values.get_or_init(|| {
if let Some(h) = handle {
h.get_header_values(&self.name).collect()
} else {
if cfg!(debug_assertions) {
panic!(
"uninitialized header values for `{}`, but no handle available",
self.name()
);
}
SmallVec::new()
}
})
}
fn first_as_owned(&self, handle: Option<&impl HandleWithHeaders>) -> Option<HeaderValue> {
if let Some(values) = self.values.get() {
values.first().cloned()
} else if let Some(handle) = handle {
handle.get_header_values(self.name()).next()
} else {
None
}
}
fn push(&mut self, handle: Option<&mut impl HandleWithHeaders>, value: impl ToHeaderValue) {
let value = value.into_borrowable();
if let Some(handle) = handle {
handle.append_header(self.name(), value.as_ref());
if let Some(values) = self.values.get_mut() {
values.push(value.into_owned());
}
} else if let Some(values) = self.values.get_mut() {
values.push(value.into_owned())
} else {
self.values = OnceCell::from(SmallVec::from_elem(value.into_owned(), 1))
}
}
fn set_to_single(&mut self, handle: Option<&mut impl HandleWithHeaders>, value: HeaderValue) {
if let Some(h) = handle {
h.set_header(self.name(), &value)
}
self.values = OnceCell::from(SmallVec::from_elem(value, 1));
}
fn into_iter(self) -> Option<impl Iterator<Item = HeaderValue>> {
self.values.into_inner().map(SmallVec::into_iter)
}
}
impl<H: HandleWithHeaders> fmt::Debug for LazyHandle<H> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<H: HandleWithHeaders> From<LazyHandle<H>> for HeaderMap {
fn from(mut val: LazyHandle<H>) -> Self {
let mut map = HeaderMap::new();
if let Some(handle) = val.handle.get() {
for name in handle.get_header_names() {
if let Some(iter) = val
.headers
.as_mut()
.swap_remove(&name)
.and_then(|v| v.make_owned().into_iter())
{
header_map_append_many(&mut map, name, iter);
} else {
header_map_append_many(&mut map, &name, handle.get_header_values(&name));
};
}
} else {
for (name, values) in val.headers.into_map() {
if let Some(iter) = values.make_owned().into_iter() {
header_map_append_many(&mut map, Rc::unwrap_or_clone(name), iter)
}
}
}
map
}
}
pub trait HandleWithHeaders: 'static {
fn new() -> Self;
fn get_header_names(&self) -> impl Iterator<Item = HeaderName>;
fn get_header_values<'a>(
&'a self,
name: &'a HeaderName,
) -> impl Iterator<Item = HeaderValue> + 'a;
fn set_header(&mut self, name: &HeaderName, value: &HeaderValue);
fn append_header(&mut self, name: &HeaderName, value: &HeaderValue);
fn remove_header(&mut self, name: &HeaderName) -> bool;
}
macro_rules! impl_handle_with_headers {
( $type:path ) => {
impl HandleWithHeaders for $type {
fn new() -> Self {
Self::new()
}
fn get_header_names(&self) -> impl Iterator<Item = HeaderName> {
self.get_header_names_impl(INITIAL_HEADER_NAME_BUF_SIZE, None)
.map(|n| n.expect("no max buffer size"))
}
fn get_header_values<'a>(
&'a self,
name: &'a HeaderName,
) -> impl Iterator<Item = HeaderValue> + 'a {
self.get_header_values_impl(name, INITIAL_HEADER_VALUE_BUF_SIZE, None)
.map(|n| n.expect("no max buffer size"))
}
fn set_header(&mut self, name: &HeaderName, value: &HeaderValue) {
self.insert_header(name, value);
}
fn append_header(&mut self, name: &HeaderName, value: &HeaderValue) {
self.append_header(name, value);
}
fn remove_header(&mut self, name: &HeaderName) -> bool {
self.remove_header(name)
}
}
};
}
impl_handle_with_headers!(RequestHandle);
impl_handle_with_headers!(ResponseHandle);
fn header_map_append_many(
map: &mut HeaderMap,
name: impl ToHeaderName,
values: impl IntoIterator<Item = HeaderValue>,
) {
let mut values = values.into_iter();
if let Some(value) = values.next() {
map.extend(
std::iter::once((Some(name.into_owned()), value)).chain(values.map(|v| (None, v))),
);
}
}
#[cfg(test)]
mod test {
use super::*;
impl HandleWithHeaders for HeaderMap {
fn new() -> Self {
HeaderMap::new()
}
fn get_header_names(&self) -> impl Iterator<Item = HeaderName> {
self.keys().cloned()
}
fn get_header_values<'a>(
&'a self,
name: &'a HeaderName,
) -> impl Iterator<Item = HeaderValue> + 'a {
self.get_all(name).into_iter().cloned()
}
fn set_header(&mut self, name: &HeaderName, value: &HeaderValue) {
self.insert(name, value.clone());
}
fn append_header(&mut self, name: &HeaderName, value: &HeaderValue) {
self.append(name, value.clone());
}
fn remove_header(&mut self, name: &HeaderName) -> bool {
self.remove(name).is_some()
}
}
fn example_map() -> HeaderMap {
let mut map = HeaderMap::new();
map.append("one", HeaderValue::from_static("a"));
map.append("two", HeaderValue::from_static("a"));
map.append("two", HeaderValue::from_static("b"));
map.append("three", HeaderValue::from_static("a"));
map.append("three", HeaderValue::from_static("b"));
map.append("three", HeaderValue::from_static("c"));
map
}
fn example_attached() -> LazyHandle<HeaderMap> {
LazyHandle::from_handle(example_map()).finish()
}
fn example_detached() -> LazyHandle<HeaderMap> {
LazyHandle::detached().with_headers(example_map()).finish()
}
fn assert_header_eq(
name: &HeaderName,
lazy: &LazyHandle<impl HandleWithHeaders>,
eager: &HeaderMap,
) {
let lazy_vec: Vec<_> = lazy.get_header_values(name).to_owned();
let eager_vec: Vec<_> = eager.get_all(name).into_iter().collect();
assert_eq!(lazy_vec, eager_vec);
}
fn assert_eq_to_map(lazy: &LazyHandle<impl HandleWithHeaders>, eager: &HeaderMap) {
for name in lazy.get_header_names() {
assert_header_eq(name, lazy, eager);
}
for name in eager.keys() {
assert_header_eq(name, lazy, eager);
}
let cloned: HeaderMap = lazy.clone().into();
assert_eq!(&cloned, eager);
}
fn reading_works(example_lazy: fn() -> LazyHandle<HeaderMap>) {
assert_eq_to_map(&example_lazy(), &example_map());
assert_eq_to_map(&example_lazy().clone(), &example_map());
let map_from_lazy: HeaderMap = example_lazy().into();
assert_eq!(map_from_lazy, example_map());
}
#[test]
fn test_reading() {
reading_works(example_attached);
reading_works(example_detached);
}
fn writing_works(mut lazy: LazyHandle<HeaderMap>, mut eager: HeaderMap) {
const ZERO: HeaderName = HeaderName::from_static("zero");
const ONE: HeaderName = HeaderName::from_static("one");
const TWO: HeaderName = HeaderName::from_static("two");
const FOUR: HeaderName = HeaderName::from_static("four");
const A: HeaderValue = HeaderValue::from_static("a");
const B: HeaderValue = HeaderValue::from_static("b");
const C: HeaderValue = HeaderValue::from_static("c");
const D: HeaderValue = HeaderValue::from_static("d");
assert_eq!(lazy.remove_header(&ZERO), eager.remove(&ZERO));
assert_header_eq(&ZERO, &lazy, &eager);
assert_eq!(lazy.remove_header(&ONE), eager.remove(&ONE));
assert_header_eq(&ONE, &lazy, &eager);
lazy.append_header_value(&ONE, A);
eager.append(&ONE, A);
assert_header_eq(&ONE, &lazy, &eager);
lazy.set_header(TWO, A);
eager.insert(TWO, A);
assert_header_eq(&TWO, &lazy, &eager);
lazy.append_header_value(&TWO, B);
eager.append(&TWO, B);
assert_header_eq(&TWO, &lazy, &eager);
for v in [A, B, C, D] {
lazy.append_header_value(&FOUR, v);
}
for v in [A, B, C, D] {
eager.append(&FOUR, v);
}
assert_header_eq(&FOUR, &lazy, &eager);
assert_eq_to_map(&lazy, &eager);
}
#[test]
fn test_writing() {
writing_works(example_attached(), example_map());
writing_works(example_detached(), example_map());
}
}