use super::{IntoResponseError, ResourceResult, handle_error}; use crate::{Response, StatusCode}; #[cfg(feature = "openapi")] use crate::OpenapiSchema; use futures_core::future::Future; use futures_util::{future, future::FutureExt}; use gotham::hyper::Body; use mime::Mime; #[cfg(feature = "openapi")] use openapiv3::{SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty}; use serde_json::error::Error as SerdeJsonError; use std::{ fmt::Display, pin::Pin }; #[derive(Debug)] pub struct Raw { pub raw : T, pub mime : Mime } impl Raw { pub fn new(raw : T, mime : Mime) -> Self { Self { raw, mime } } } impl Clone for Raw { fn clone(&self) -> Self { Self { raw: self.raw.clone(), mime: self.mime.clone() } } } impl> ResourceResult for Raw where Self : Send { type Err = SerdeJsonError; // just for easier handling of `Result, E>` fn into_response(self) -> Pin> + Send>> { future::ok(Response::new(StatusCode::OK, self.raw, Some(self.mime.clone()))).boxed() } #[cfg(feature = "openapi")] fn schema() -> OpenapiSchema { OpenapiSchema::new(SchemaKind::Type(Type::String(StringType { format: VariantOrUnknownOrEmpty::Item(StringFormat::Binary), ..Default::default() }))) } } impl ResourceResult for Result, E> where Raw : ResourceResult, E : Display + IntoResponseError as ResourceResult>::Err> { type Err = E::Err; fn into_response(self) -> Pin> + Send>> { match self { Ok(raw) => raw.into_response(), Err(e) => handle_error(e) } } #[cfg(feature = "openapi")] fn schema() -> OpenapiSchema { as ResourceResult>::schema() } } #[cfg(test)] mod test { use super::*; use futures_executor::block_on; use mime::TEXT_PLAIN; #[test] fn raw_response() { let msg = "Test"; let raw = Raw::new(msg, TEXT_PLAIN); let res = block_on(raw.into_response()).expect("didn't expect error response"); assert_eq!(res.status, StatusCode::OK); assert_eq!(res.mime, Some(TEXT_PLAIN)); assert_eq!(res.full_body().unwrap(), msg.as_bytes()); } }