tests.rs (2481B)
1 use crate::error::TestErrors; 2 use rocket::data::{FromData, FromDataFuture, Transform, TransformFuture, Transformed}; 3 use rocket::http::ContentType; 4 use rocket::http::Status; 5 use rocket::response::Responder; 6 use rocket::response::{self, Response}; 7 use rocket::{Data, Outcome::*, Request}; 8 use serde::{Deserialize, Serialize}; 9 use std::io::Cursor; 10 use tokio::io::AsyncReadExt; 11 12 #[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq)] 13 #[serde(tag = "test")] 14 #[serde(rename_all = "snake_case")] 15 pub enum Tests { 16 Start, 17 SyncTimeout, 18 } 19 20 impl Default for Tests { 21 fn default() -> Self { 22 Tests::Start 23 } 24 } 25 26 impl<'a> FromData<'a> for Tests { 27 type Error = TestErrors; 28 type Owned = String; 29 type Borrowed = str; 30 31 fn transform<'r>( 32 request: &'r Request<'_>, 33 data: Data, 34 ) -> TransformFuture<'r, Self::Owned, Self::Error> { 35 Box::pin(async move { 36 let mut stream = data.open(); 37 let mut string = String::new(); 38 let outcome = match stream.read_to_string(&mut string).await { 39 Ok(_) => Success(string), 40 Err(e) => Failure((Status::InternalServerError, TestErrors::Io(e))), 41 }; 42 43 // Returning `Borrowed` here means we get `Borrowed` in `from_data`. 44 Transform::Borrowed(outcome) 45 }) 46 } 47 48 fn from_data( 49 request: &'a Request<'_>, 50 outcome: Transformed<'a, Self>, 51 ) -> FromDataFuture<'a, Self, Self::Error> { 52 Box::pin(async move { 53 // Retrieve a borrow to the now transformed `String` (an &str). This 54 // is only correct because we know we _always_ return a `Borrowed` from 55 // `transform` above. 56 let data = try_outcome!(outcome.borrowed()); 57 58 let test_enum: Tests = serde_json::from_str(data).unwrap(); 59 Success(test_enum) 60 }) 61 } 62 } 63 64 /// This struct converts test responses into rocket http responses. 65 pub struct TestsResult(pub std::result::Result<Tests, TestErrors>); 66 67 #[rocket::async_trait] 68 impl<'r> Responder<'r> for TestsResult { 69 async fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> { 70 match self.0 { 71 Ok(v) => Response::build() 72 .header(ContentType::JSON) 73 .sized_body(Cursor::new(serde_json::to_string(&v).unwrap())) 74 .await 75 .ok(), 76 Err(v) => Err(Status::InternalServerError), 77 } 78 } 79 }