tenebrous-sheets/src/models/proto.rs

71 lines
1.9 KiB
Rust

use crate::errors::Error;
use rocket::data::{Data, FromData, Outcome, ToByteUnit};
use rocket::request::Request;
use std::default::Default;
use std::ops::Deref;
/// Contains the generated Chronicles of Darkness-related protocol
/// buffer types.
pub mod cofd {
include!(concat!(env!("OUT_DIR"), "/models.proto.cofd.rs"));
pub mod api {
include!(concat!(env!("OUT_DIR"), "/models.proto.cofd.api.rs"));
}
// TODO these values are not available in tera templates, so how to
// handle?
pub(crate) trait DerivedStats {
fn speed(&self) -> i32;
}
impl DerivedStats for CofdSheet {
fn speed(&self) -> i32 {
self.size + self.stamina
}
}
}
/// 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>(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<T> FromData for Proto<T>
where
T: prost::Message + Default,
{
type Error = crate::errors::Error;
async fn from_data(_req: &Request<'_>, data: Data) -> Outcome<Self, Error> {
use rocket::http::Status;
let bytes: Vec<u8> = 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())),
}
}
}
impl<T> Deref for Proto<T>
where
T: prost::Message + Default,
{
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}