use crate::errors::Error; use rocket::data::{Data, FromData, Outcome, ToByteUnit}; use rocket::request::Request; use std::default::Default; use std::ops::Deref; pub mod cofd; /// A struct wrapping a protobuf that allows it to be used as binary /// data submitted via POST using fetch API. Can automatically be /// dereferenced into its wrapped type. #[derive(Debug)] pub(crate) struct Proto(T) where T: prost::Message + Default; /// Converts the body of a POST request containing encoded protobuf /// data into the wrapped type. #[rocket::async_trait] impl FromData for Proto where T: prost::Message + Default, { type Error = crate::errors::Error; async fn from_data(_req: &Request<'_>, data: Data) -> Outcome { use rocket::http::Status; let bytes: Vec = match data.open(2.mebibytes()).stream_to_vec().await { Ok(read_bytes) => read_bytes, Err(e) => return Outcome::Failure((Status::new(422, "invalid protobuf"), e.into())), }; match T::decode(bytes.as_ref()) { Ok(decoded) => Outcome::Success(Proto(decoded)), Err(e) => Outcome::Failure((Status::new(422, "invalid protobuf"), e.into())), } } } /// Enable automatically calling methods on a decoded Proto instance. impl Deref for Proto where T: prost::Message + Default, { type Target = T; fn deref(&self) -> &T { &self.0 } }