rama_http/service/web/endpoint/response/
csv.rs1use super::IntoResponse;
2use crate::{Body, Response, dep::http::StatusCode};
3use bytes::buf::Writer;
4use bytes::{BufMut, BytesMut};
5use csv;
6use rama_core::error::OpaqueError;
7use rama_http_headers::ContentType;
8use rama_utils::macros::impl_deref;
9use serde::Serialize;
10use std::fmt;
11
12use super::Headers;
13
14pub struct Csv<T>(pub T);
63
64impl<T: fmt::Debug> fmt::Debug for Csv<T> {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 f.debug_tuple("Csv").field(&self.0).finish()
67 }
68}
69
70impl<T: Clone> Clone for Csv<T> {
71 fn clone(&self) -> Self {
72 Self(self.0.clone())
73 }
74}
75
76impl_deref!(Csv);
77
78impl<T> From<T> for Csv<T> {
79 fn from(inner: T) -> Self {
80 Self(inner)
81 }
82}
83
84impl<T> IntoResponse for Csv<T>
85where
86 T: IntoIterator<Item: Serialize> + std::fmt::Debug,
87{
88 fn into_response(self) -> Response {
89 fn make_respone(
91 res: csv::Result<Vec<()>>,
92 mut wtr: csv::Writer<Writer<BytesMut>>,
93 ) -> Response {
94 if let Err(err) = res {
95 return (
96 StatusCode::INTERNAL_SERVER_ERROR,
97 Headers::single(ContentType::text_utf8()),
98 err.to_string(),
99 )
100 .into_response();
101 }
102 if let Err(err) = wtr.flush() {
103 return (
104 StatusCode::INTERNAL_SERVER_ERROR,
105 Headers::single(ContentType::text_utf8()),
106 err.to_string(),
107 )
108 .into_response();
109 }
110
111 let bw = match wtr.into_inner() {
112 Ok(bw) => bw,
113 Err(err) => {
114 return (
115 StatusCode::INTERNAL_SERVER_ERROR,
116 Headers::single(ContentType::text_utf8()),
117 err.to_string(),
118 )
119 .into_response();
120 }
121 };
122
123 (
124 Headers::single(ContentType::csv_utf8()),
125 bw.into_inner().freeze(),
126 )
127 .into_response()
128 }
129
130 let buf = BytesMut::with_capacity(128).writer();
133
134 let mut wtr = csv::Writer::from_writer(buf);
135 let res: Result<Vec<_>, _> = self.0.into_iter().map(|rec| wtr.serialize(rec)).collect();
136
137 make_respone(res, wtr)
138 }
139}
140
141impl<T> TryInto<Body> for Csv<T>
142where
143 T: IntoIterator<Item: Serialize>,
144{
145 type Error = OpaqueError;
146
147 fn try_into(self) -> Result<Body, Self::Error> {
148 let mut buf = BytesMut::with_capacity(128).writer();
151 {
152 let mut wtr = csv::Writer::from_writer(&mut buf);
153 let res: Result<Vec<_>, _> = self.0.into_iter().map(|rec| wtr.serialize(rec)).collect();
154 if let Err(err) = res {
155 return Err(OpaqueError::from_std(err));
156 }
157 if let Err(err) = wtr.flush() {
158 return Err(OpaqueError::from_std(err));
159 }
160 }
161
162 Ok(buf.into_inner().freeze().into())
163 }
164}