use spacetimedb_sats::{time_duration::TimeDuration, SpacetimeType};
#[derive(Clone, SpacetimeType)]
#[sats(crate = crate, name = "HttpRequest")]
pub struct Request {
pub method: Method,
pub headers: Headers,
pub timeout: Option<TimeDuration>,
pub uri: String,
pub version: Version,
}
impl Request {
pub fn size_in_bytes(&self) -> usize {
self.uri.len() + self.headers.size_in_bytes()
}
}
#[derive(Clone, SpacetimeType, PartialEq, Eq)]
#[sats(crate = crate, name = "HttpMethod")]
pub enum Method {
Get,
Head,
Post,
Put,
Delete,
Connect,
Options,
Trace,
Patch,
Extension(String),
}
#[derive(Clone, SpacetimeType, PartialEq, Eq)]
#[sats(crate = crate, name = "HttpVersion")]
pub enum Version {
Http09,
Http10,
Http11,
Http2,
Http3,
}
#[derive(Clone, SpacetimeType)]
#[sats(crate = crate, name = "HttpHeaders")]
pub struct Headers {
entries: Box<[HttpHeaderPair]>,
}
struct HeaderIter<I, T> {
prev: Option<(Box<str>, T)>,
inner: I,
}
impl<I, T> Iterator for HeaderIter<I, T>
where
I: Iterator<Item = (Option<Box<str>>, T)>,
{
type Item = (Box<str>, T);
fn next(&mut self) -> Option<Self::Item> {
let (prev_k, prev_v) = self
.prev
.take()
.or_else(|| self.inner.next().map(|(k, v)| (k.unwrap(), v)))?;
self.prev = self
.inner
.next()
.map(|(next_k, next_v)| (next_k.unwrap_or_else(|| prev_k.clone()), next_v));
Some((prev_k, prev_v))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl FromIterator<(Option<Box<str>>, Box<[u8]>)> for Headers {
fn from_iter<T: IntoIterator<Item = (Option<Box<str>>, Box<[u8]>)>>(iter: T) -> Self {
let inner = iter.into_iter();
let entries = HeaderIter { prev: None, inner }
.map(|(name, value)| HttpHeaderPair { name, value })
.collect();
Self { entries }
}
}
impl Headers {
#[allow(clippy::should_implement_trait)]
pub fn into_iter(self) -> impl Iterator<Item = (Box<str>, Box<[u8]>)> {
IntoIterator::into_iter(self.entries).map(|HttpHeaderPair { name, value }| (name, value))
}
fn size_in_bytes(&self) -> usize {
self.entries
.iter()
.map(|HttpHeaderPair { name, value }| name.len() + value.len())
.sum::<usize>()
}
}
#[derive(Clone, SpacetimeType)]
#[sats(crate = crate, name = "HttpHeaderPair")]
struct HttpHeaderPair {
name: Box<str>,
value: Box<[u8]>,
}
#[derive(Clone, SpacetimeType)]
#[sats(crate = crate, name = "HttpResponse")]
pub struct Response {
pub headers: Headers,
pub version: Version,
pub code: u16,
}
impl Response {
pub fn size_in_bytes(&self) -> usize {
self.headers.size_in_bytes()
}
}