use super::IntoResponse;
use crate::{Body, Response, StatusCode};
use csv;
use rama_core::bytes::buf::Writer;
use rama_core::bytes::{BufMut, BytesMut};
use rama_core::error::BoxError;
use rama_http_headers::ContentType;
use rama_utils::macros::impl_deref;
use serde::Serialize;
use super::Headers;
#[derive(Debug, Clone, Copy)]
pub struct Csv<T>(pub T);
impl_deref!(Csv);
impl<T> From<T> for Csv<T> {
fn from(inner: T) -> Self {
Self(inner)
}
}
impl<T> IntoResponse for Csv<T>
where
T: IntoIterator<Item: Serialize> + std::fmt::Debug,
{
fn into_response(self) -> Response {
fn make_response(
res: csv::Result<Vec<()>>,
mut wtr: csv::Writer<Writer<BytesMut>>,
) -> Response {
if let Err(err) = res {
return (
StatusCode::INTERNAL_SERVER_ERROR,
Headers::single(ContentType::text_utf8()),
err.to_string(),
)
.into_response();
}
if let Err(err) = wtr.flush() {
return (
StatusCode::INTERNAL_SERVER_ERROR,
Headers::single(ContentType::text_utf8()),
err.to_string(),
)
.into_response();
}
let bw = match wtr.into_inner() {
Ok(bw) => bw,
Err(err) => {
return (
StatusCode::INTERNAL_SERVER_ERROR,
Headers::single(ContentType::text_utf8()),
err.to_string(),
)
.into_response();
}
};
(
Headers::single(ContentType::csv_utf8()),
bw.into_inner().freeze(),
)
.into_response()
}
let buf = BytesMut::with_capacity(128).writer();
let mut wtr = csv::Writer::from_writer(buf);
let res: Result<Vec<_>, _> = self.0.into_iter().map(|rec| wtr.serialize(rec)).collect();
make_response(res, wtr)
}
}
impl<T> TryFrom<Csv<T>> for Body
where
T: IntoIterator<Item: Serialize>,
{
type Error = BoxError;
fn try_from(csv: Csv<T>) -> Result<Self, Self::Error> {
let mut buf = BytesMut::with_capacity(128).writer();
{
let mut wtr = csv::Writer::from_writer(&mut buf);
let res: Result<Vec<_>, _> = csv.0.into_iter().map(|rec| wtr.serialize(rec)).collect();
if let Err(err) = res {
return Err(BoxError::from(err));
}
if let Err(err) = wtr.flush() {
return Err(BoxError::from(err));
}
}
Ok(buf.into_inner().freeze().into())
}
}