use rocket::response::{Response, Responder};
use rocket::http::{Status, ContentType};
use rocket::request::Request;
use std::result;
use std::sync::Arc;
use std::path::PathBuf;
use std::io;
use sized_file::SizedFile;
#[derive(Debug, Clone)]
pub struct CachedFile {
pub(crate) path: PathBuf,
pub(crate) file: Arc<SizedFile>,
}
impl CachedFile {
pub fn open(path: PathBuf) -> io::Result<CachedFile> {
let sized_file: SizedFile = SizedFile::open(&path)?;
Ok(CachedFile {
path,
file: Arc::new(sized_file)
})
}
#[inline]
pub(crate) fn set_response_body(self, response: &mut Response) {
let file: *const SizedFile = Arc::into_raw(self.file);
unsafe {
response.set_streamed_body((*file).bytes.as_slice());
let _ = Arc::from_raw(file); }
}
}
impl Responder<'static> for CachedFile {
fn respond_to(self, _: &Request) -> result::Result<Response<'static>, Status> {
let mut response = Response::new();
if let Some(ext) = self.path.extension() {
if let Some(ct) = ContentType::from_extension(&ext.to_string_lossy()) {
response.set_header(ct);
}
}
self.set_response_body(&mut response);
Ok(response)
}
}