serde_stream_formats/
encode.rs1use std::fmt;
4use std::io::{
5 self,
6 Write as IoWrite,
7};
8use std::pin::Pin;
9use std::task::{
10 Context,
11 Poll,
12};
13
14use bytes::Bytes;
15use serde::Serialize;
16use tokio::sync::mpsc;
17use tokio_stream::Stream;
18use tokio_stream::wrappers::ReceiverStream;
19
20use crate::error::FormatError;
21
22const SERIALIZER_CHANNEL_CAPACITY: usize = 8;
25const MAX_SERIALIZER_CHUNK_BYTES: usize = 64 * 1024;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum EncodeFormat {
31 Json,
33 Yaml,
35 MessagePack,
38 Postcard,
40}
41
42impl EncodeFormat {
43 #[must_use]
45 pub const fn media_type(self) -> &'static str {
46 match self {
47 Self::Json => "application/json",
48 Self::Yaml => "application/yaml",
49 Self::MessagePack => "application/vnd.msgpack",
50 Self::Postcard => "application/x-postcard",
51 }
52 }
53
54 #[must_use]
56 pub const fn name(self) -> &'static str {
57 match self {
58 Self::Json => "JSON",
59 Self::Yaml => "YAML",
60 Self::MessagePack => "MessagePack",
61 Self::Postcard => "Postcard",
62 }
63 }
64
65 #[must_use]
70 pub fn from_content_type(content_type: &str) -> Option<Self> {
71 let media_type = content_type
72 .split(';')
73 .next()
74 .unwrap_or_default()
75 .trim()
76 .to_ascii_lowercase();
77 match media_type.as_str() {
78 "application/json" => Some(Self::Json),
79 "application/yaml" | "application/x-yaml" | "text/yaml" => Some(Self::Yaml),
80 "application/vnd.msgpack" | "application/msgpack" | "application/x-msgpack" => {
81 Some(Self::MessagePack)
82 }
83 "application/x-postcard" => Some(Self::Postcard),
84 _ => None,
85 }
86 }
87
88 pub fn encode_vec<T: Serialize>(self, value: &T) -> Result<Vec<u8>, FormatError> {
99 match self {
100 Self::Json => serde_json::to_vec(value).map_err(|error| self.unencodable(error)),
101 Self::Yaml => serde_yaml2::to_string(value)
102 .map(String::into_bytes)
103 .map_err(|error| self.unencodable(error)),
104 Self::MessagePack => {
105 rmp_serde::to_vec_named(value).map_err(|error| self.unencodable(error))
106 }
107 Self::Postcard => postcard::to_allocvec(value).map_err(|error| self.unencodable(error)),
108 }
109 }
110
111 pub fn encode_stream<T>(self, value: T) -> EncodedStream
122 where
123 T: Serialize + Send + 'static,
124 {
125 let (sender, receiver) = mpsc::channel(SERIALIZER_CHANNEL_CAPACITY);
126 tokio::task::spawn_blocking(move || {
127 let mut writer = ChannelWriter { sender };
128 let result = match self {
129 Self::Json => {
130 serde_json::to_writer(&mut writer, &value).map_err(|error| error.to_string())
131 }
132 Self::Yaml => {
133 let mut formatter = ChannelFormatter {
134 writer: &mut writer,
135 };
136 let mut serializer = serde_yaml2::ser::YamlSerializer::new(&mut formatter);
137 serializer.write(value).map_err(|error| error.to_string())
138 }
139 Self::MessagePack => value
140 .serialize(&mut rmp_serde::Serializer::new(&mut writer).with_struct_map())
141 .map_err(|error| error.to_string()),
142 Self::Postcard => postcard::to_io(&value, &mut writer)
143 .map(|_| ())
144 .map_err(|error| error.to_string()),
145 };
146 if let Err(error) = result {
147 let format_error = self.unencodable(error);
148 let _ = writer.sender.blocking_send(Err(format_error));
149 }
150 });
151 EncodedStream {
152 inner: ReceiverStream::new(receiver),
153 }
154 }
155
156 fn unencodable(self, error: impl std::fmt::Display) -> FormatError {
157 FormatError::Encoding {
158 format: self.name(),
159 detail: error.to_string(),
160 }
161 }
162}
163
164#[derive(Debug)]
166pub struct EncodedStream {
167 inner: ReceiverStream<Result<Bytes, FormatError>>,
168}
169
170impl Stream for EncodedStream {
171 type Item = Result<Bytes, FormatError>;
172
173 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
174 Pin::new(&mut self.inner).poll_next(cx)
175 }
176}
177
178struct ChannelWriter {
180 sender: mpsc::Sender<Result<Bytes, FormatError>>,
181}
182
183impl IoWrite for ChannelWriter {
184 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
185 if bytes.is_empty() {
186 return Ok(0);
187 }
188 for chunk in bytes.chunks(MAX_SERIALIZER_CHUNK_BYTES) {
189 self.sender
190 .blocking_send(Ok(Bytes::copy_from_slice(chunk)))
191 .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "encoded stream dropped"))?;
192 }
193 Ok(bytes.len())
194 }
195
196 fn flush(&mut self) -> io::Result<()> {
197 Ok(())
198 }
199}
200
201struct ChannelFormatter<'a> {
203 writer: &'a mut ChannelWriter,
204}
205
206impl fmt::Write for ChannelFormatter<'_> {
207 fn write_str(&mut self, value: &str) -> fmt::Result {
208 self.writer
209 .write_all(value.as_bytes())
210 .map_err(|_| fmt::Error)
211 }
212}