use crate::{CodeMessage, Result};
use anyhow::Context as _;
use serde::de::DeserializeOwned;
use tracing::debug;
pub static CODE_MESSAGE: CodeMessage = CodeMessage {
code: String::new(),
message: String::new(),
};
pub trait ToCodeMessage {
fn to_code_message(&self) -> &CodeMessage;
}
pub trait FromBody: Sized {
fn from_body(bytes: Vec<u8>) -> Result<Self>;
}
pub trait IntoResponse {
type Response;
fn into_response(self) -> Self::Response;
}
pub trait BinaryWithMeta {
fn set_binary(&mut self, body: Vec<u8>);
}
#[derive(Debug)]
pub struct JsonResponseWrap<T> {
pub inner: T,
}
impl<T: DeserializeOwned> FromBody for JsonResponseWrap<T> {
fn from_body(bytes: Vec<u8>) -> Result<Self> {
let text = String::from_utf8(bytes).context("Response body is not valid UTF-8")?;
debug!("Response: {}", text);
let inner = serde_json::from_str(&text)
.with_context(|| format!("Decode response as JSON: {}", &text))?;
Ok(Self { inner })
}
}
impl<T: ToCodeMessage> ToCodeMessage for JsonResponseWrap<T> {
fn to_code_message(&self) -> &CodeMessage {
self.inner.to_code_message()
}
}
impl<T> IntoResponse for JsonResponseWrap<T> {
type Response = T;
fn into_response(self) -> Self::Response {
self.inner
}
}
#[derive(Debug)]
pub struct SelfResponseWrap<T> {
pub inner: T,
}
impl<T> IntoResponse for SelfResponseWrap<T> {
type Response = T;
fn into_response(self) -> Self::Response {
self.inner
}
}
impl<T: Default> FromBody for SelfResponseWrap<T> {
fn from_body(_bytes: Vec<u8>) -> Result<Self> {
Ok(SelfResponseWrap {
inner: T::default(),
})
}
}
impl<T> ToCodeMessage for SelfResponseWrap<T> {
fn to_code_message(&self) -> &CodeMessage {
&CODE_MESSAGE
}
}
impl FromBody for () {
fn from_body(_bytes: Vec<u8>) -> Result<Self> {
Ok(())
}
}
impl ToCodeMessage for () {
fn to_code_message(&self) -> &CodeMessage {
&CODE_MESSAGE
}
}
impl IntoResponse for () {
type Response = ();
fn into_response(self) -> Self::Response {
self
}
}
#[derive(Debug)]
pub struct XmlResponseWrap<T> {
pub inner: T,
}
impl<T: DeserializeOwned> FromBody for XmlResponseWrap<T> {
fn from_body(bytes: Vec<u8>) -> Result<Self> {
let inner = quick_xml::de::from_reader(&bytes[..]).context("Decode response as XML")?;
Ok(Self { inner })
}
}
impl<T: ToCodeMessage> ToCodeMessage for XmlResponseWrap<T> {
fn to_code_message(&self) -> &CodeMessage {
self.inner.to_code_message()
}
}
impl<T> IntoResponse for XmlResponseWrap<T> {
type Response = T;
fn into_response(self) -> Self::Response {
self.inner
}
}
#[derive(Debug)]
pub struct BinaryResponseWrap {
pub inner: Vec<u8>,
}
impl FromBody for BinaryResponseWrap {
fn from_body(bytes: Vec<u8>) -> Result<Self> {
Ok(Self { inner: bytes })
}
}
impl ToCodeMessage for BinaryResponseWrap {
fn to_code_message(&self) -> &CodeMessage {
&CODE_MESSAGE
}
}
impl IntoResponse for BinaryResponseWrap {
type Response = Vec<u8>;
fn into_response(self) -> Self::Response {
self.inner
}
}
#[derive(Debug)]
pub struct BinaryResponseWithMetaWrap<T: BinaryWithMeta + Default> {
pub inner: T,
}
impl<T: BinaryWithMeta + Default> FromBody for BinaryResponseWithMetaWrap<T> {
fn from_body(bytes: Vec<u8>) -> Result<Self> {
let mut inner: T = Default::default();
inner.set_binary(bytes);
Ok(Self { inner })
}
}
impl<T: BinaryWithMeta + Default> ToCodeMessage for BinaryResponseWithMetaWrap<T> {
fn to_code_message(&self) -> &CodeMessage {
&CODE_MESSAGE
}
}
impl<T: BinaryWithMeta + Default> IntoResponse for BinaryResponseWithMetaWrap<T> {
type Response = T;
fn into_response(self) -> Self::Response {
self.inner
}
}