use crate::handler::Handler;
use crate::http::headers::Line;
use crate::http::request::Request;
use crate::http::response::StatusCode;
use crate::http::OwnedOrStatic;
use bytes::Bytes;
use rocket::http::uri::Path;
use rocket::http::{Header, Status};
use rocket::route::Handler as RocketHandler;
use rocket::route::Outcome;
use rocket::serde::__private::from_utf8_lossy;
use rocket::{Data, Request as RocketRequest, Response};
use std::borrow::Cow;
use std::io::Cursor;
use std::str::from_utf8;
use std::sync::Arc;
#[derive(Clone)]
pub struct HandlerAdapter;
#[rocket::async_trait]
impl RocketHandler for HandlerAdapter {
async fn handle<'r>(&self, request: &'r RocketRequest<'_>, _data: Data<'r>) -> Outcome<'r> {
let path = request.uri().path();
request
.rocket()
.state::<Arc<Handler>>()
.unwrap()
.handle(RequestAdapter {
inner: request,
path,
})
}
}
struct RequestAdapter<'r, 'o> {
inner: &'r RocketRequest<'o>,
path: Path<'r>,
}
impl<'r> Request<Outcome<'r>> for RequestAdapter<'r, '_> {
fn method(&self) -> &[u8] {
self.inner.method().as_str().as_bytes()
}
fn path(&self) -> &[u8] {
self.path.as_bytes()
}
fn first_header_value(&self, key: &'static [u8]) -> Option<&[u8]> {
from_utf8(key)
.ok()
.and_then(|key| self.inner.headers().get_one(key).map(|it| it.as_bytes()))
}
fn response<'a>(
self,
code: StatusCode,
headers: impl Iterator<Item = &'a Line>,
body: Option<Bytes>,
) -> Outcome<'r> {
let code: u16 = code.into();
let mut builder = Response::build();
builder.status(Status::new(code));
headers.for_each(|ref line| {
let line = line.as_ref().clone();
builder.header(Header::new(
from_utf8_lossy(line.key),
match line.value {
OwnedOrStatic::Owned(vec) => Cow::Owned(from_utf8_lossy(&vec).to_string()),
OwnedOrStatic::Static(slice) => from_utf8_lossy(slice),
},
));
});
if let Some(bytes) = body {
let len = bytes.len();
builder.sized_body(Some(len), Cursor::new(bytes));
}
Outcome::Success(builder.finalize())
}
}