use std::{error::Error, marker::PhantomData, sync::Arc};
use rocket::{
data::ByteUnit,
fairing::{self, Fairing, Info, Kind},
Build, Ignite, Orbit, Phase, Rocket,
};
use crate::{
fs::Terminated,
handlers::{
creation_handler, file_info_handler, info_handler, termination_handler,
upload_handler,
},
};
#[allow(unused_imports)]
use crate::{
fs::{Built, Completed, Created, LocalVault, Metadata},
handlers::HandlerContext,
MeteoritusHeaders, Vault,
};
#[derive(Clone)]
pub struct Meteoritus<P: Phase> {
auto_terminate: bool,
base_route: &'static str,
max_size: ByteUnit,
vault: Arc<dyn Vault>,
on_creation: Option<
Arc<
dyn Fn(HandlerContext<Built>) -> Result<(), Box<dyn Error>>
+ Send
+ Sync,
>,
>,
on_created: Option<Arc<dyn Fn(HandlerContext<Created>) + Send + Sync>>,
on_completed: Option<Arc<dyn Fn(HandlerContext<Completed>) + Send + Sync>>,
on_termination:
Option<Arc<dyn Fn(HandlerContext<Terminated>) + Send + Sync>>,
state: std::marker::PhantomData<P>,
}
impl<P: Phase> Meteoritus<P> {
pub fn get_protocol_version(&self) -> MeteoritusHeaders {
MeteoritusHeaders::Version(&["1.0.0"])
}
pub fn get_protocol_resumable_version(&self) -> MeteoritusHeaders {
MeteoritusHeaders::Resumable("1.0.0")
}
pub fn get_protocol_extensions(&self) -> MeteoritusHeaders {
MeteoritusHeaders::Extensions(&["creation", "termination"])
}
pub fn get_protocol_max_size(&self) -> MeteoritusHeaders {
MeteoritusHeaders::MaxSize(self.max_size.as_u64())
}
}
impl Meteoritus<Build> {
pub fn new() -> Meteoritus<Build> {
Meteoritus::<Build> {
auto_terminate: true,
base_route: "/meteoritus",
max_size: ByteUnit::Megabyte(5),
vault: Arc::new(LocalVault::new("./tmp/files")),
on_creation: Default::default(),
on_created: Default::default(),
on_completed: Default::default(),
on_termination: Default::default(),
state: PhantomData::<Build>,
}
}
pub fn build(self) -> Meteoritus<Ignite> {
Meteoritus::<Ignite> {
state: std::marker::PhantomData,
auto_terminate: self.auto_terminate,
base_route: self.base_route,
max_size: self.max_size,
vault: self.vault,
on_creation: self.on_creation,
on_created: self.on_created,
on_completed: self.on_completed,
on_termination: self.on_termination,
}
}
pub fn keep_on_disk(mut self) -> Self {
self.auto_terminate = false;
self
}
pub fn mount_to(mut self, base_route: &'static str) -> Self {
self.base_route = base_route;
self
}
pub fn with_temp_path(self, temp_path: &'static str) -> Self {
self.with_vault(LocalVault::new(temp_path))
}
#[doc(hidden)]
pub(crate) fn with_vault<V: Vault + 'static>(mut self, vault: V) -> Self {
self.vault = Arc::new(vault);
self
}
pub fn with_max_size(mut self, size: ByteUnit) -> Self {
self.max_size = size;
self
}
pub fn on_creation<F>(mut self, callback: F) -> Self
where
F: Fn(HandlerContext<Built>) -> Result<(), Box<dyn Error>>
+ Send
+ Sync
+ 'static,
{
self.on_creation = Some(Arc::new(callback));
self
}
pub fn on_created<F>(mut self, callback: F) -> Self
where
F: Fn(HandlerContext<Created>) + Send + Sync + 'static,
{
self.on_created = Some(Arc::new(callback));
self
}
pub fn on_completed<F>(mut self, callback: F) -> Self
where
F: Fn(HandlerContext<Completed>) + Send + Sync + 'static,
{
self.on_completed = Some(Arc::new(callback));
self
}
pub fn on_termination<F>(mut self, callback: F) -> Self
where
F: Fn(HandlerContext<Terminated>) + Send + Sync + 'static,
{
self.on_termination = Some(Arc::new(callback));
self
}
}
impl Meteoritus<Ignite> {
pub(crate) fn launch(&self) -> Meteoritus<Orbit> {
Meteoritus::<Orbit> {
state: std::marker::PhantomData,
auto_terminate: self.auto_terminate,
base_route: self.base_route,
max_size: self.max_size,
vault: self.vault.to_owned(),
on_creation: self.on_creation.to_owned(),
on_created: self.on_created.to_owned(),
on_completed: self.on_completed.to_owned(),
on_termination: self.on_termination.to_owned(),
}
}
}
impl Meteoritus<Orbit> {
pub fn base_route(&self) -> &str {
self.base_route
}
pub fn auto_terminate(&self) -> bool {
self.auto_terminate
}
pub fn max_size(&self) -> ByteUnit {
self.max_size
}
pub(crate) fn on_creation(
&self,
) -> &Option<
Arc<
dyn Fn(HandlerContext<Built>) -> Result<(), Box<dyn Error>>
+ Send
+ Sync,
>,
> {
&self.on_creation
}
pub(crate) fn on_created(
&self,
) -> &Option<Arc<dyn Fn(HandlerContext<Created>) + Send + Sync>> {
&self.on_created
}
pub(crate) fn on_completed(
&self,
) -> &Option<Arc<dyn Fn(HandlerContext<Completed>) + Send + Sync>> {
&self.on_completed
}
pub(crate) fn on_termination(
&self,
) -> &Option<Arc<dyn Fn(HandlerContext<Terminated>) + Send + Sync>> {
&self.on_termination
}
}
#[rocket::async_trait]
impl Fairing for Meteoritus<Ignite> {
fn info(&self) -> Info {
Info {
name: "Meteoritus",
kind: Kind::Ignite,
}
}
async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {
let routes = routes![
creation_handler,
info_handler,
file_info_handler,
termination_handler,
upload_handler,
];
Ok(rocket
.manage(self.launch())
.manage(self.vault.to_owned())
.mount(self.base_route, routes))
}
}