axum_codec/
encode.rs

1use axum::response::{IntoResponse, Response};
2
3use crate::{Codec, ContentType};
4
5crate::macros::__private_encode_trait! {
6	/// Encoder trait for encoding a value into any supported format.
7	///
8	/// Note that feature flags affect this trait differently than normal. In this case,
9	/// feature flags further restrict the trait instead of being additive. This may change
10	/// in the future.
11}
12
13/// Errors that can occur during encoding.
14///
15/// In debug mode this will include the error message. In release mode it will
16/// only include a status code of `500 Internal Server Error`.
17#[derive(Debug, thiserror::Error)]
18#[non_exhaustive]
19pub enum Error {
20	#[cfg(feature = "json")]
21	#[error(transparent)]
22	Json(#[from] serde_json::Error),
23	#[cfg(feature = "form")]
24	#[error(transparent)]
25	Form(#[from] serde_urlencoded::ser::Error),
26	#[cfg(feature = "msgpack")]
27	#[error(transparent)]
28	MsgPack(#[from] rmp_serde::encode::Error),
29	#[cfg(feature = "cbor")]
30	#[error(transparent)]
31	Cbor(#[from] ciborium::ser::Error<std::io::Error>),
32	#[cfg(feature = "bincode")]
33	#[error(transparent)]
34	Bincode(#[from] bincode::error::EncodeError),
35	#[cfg(feature = "yaml")]
36	#[error(transparent)]
37	Yaml(#[from] serde_yaml::Error),
38	#[cfg(feature = "toml")]
39	#[error(transparent)]
40	Toml(#[from] toml::ser::Error),
41}
42
43impl IntoResponse for Error {
44	fn into_response(self) -> Response {
45		use axum::http::StatusCode;
46
47		#[cfg(debug_assertions)]
48		return (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response();
49		#[cfg(not(debug_assertions))]
50		StatusCode::INTERNAL_SERVER_ERROR.into_response()
51	}
52}
53
54#[cfg(feature = "serde")]
55impl<T> Codec<T>
56where
57	T: serde::Serialize,
58{
59	/// Attempts to serialize the given value as [JSON](https://www.json.org).
60	///
61	/// # Errors
62	///
63	/// See [`serde_json::to_vec`].
64	#[cfg(feature = "json")]
65	#[inline]
66	pub fn to_json(&self) -> Result<Vec<u8>, serde_json::Error> {
67		serde_json::to_vec(&self.0)
68	}
69
70	/// Attempts to serialize the given value as [URL-encoded form data](https://url.spec.whatwg.org/#urlencoded-parsing).
71	///
72	/// # Errors
73	///
74	/// See [`serde_urlencoded::to_string`].
75	#[cfg(feature = "form")]
76	#[inline]
77	pub fn to_form(&self) -> Result<Vec<u8>, serde_urlencoded::ser::Error> {
78		serde_urlencoded::to_string(&self.0).map(String::into_bytes)
79	}
80
81	/// Attempts to serialize the given value as [MessagePack](https://msgpack.org).
82	///
83	/// # Errors
84	///
85	/// See [`rmp_serde::to_vec_named`].
86	#[cfg(feature = "msgpack")]
87	#[inline]
88	pub fn to_msgpack(&self) -> Result<Vec<u8>, rmp_serde::encode::Error> {
89		rmp_serde::to_vec_named(&self.0)
90	}
91
92	/// Attempts to serialize the given value as [CBOR](https://cbor.io).
93	///
94	/// # Errors
95	///
96	/// See [`ciborium::into_writer`].
97	#[cfg(feature = "cbor")]
98	#[inline]
99	pub fn to_cbor(&self) -> Result<Vec<u8>, ciborium::ser::Error<std::io::Error>> {
100		let mut buf = Vec::new();
101		ciborium::into_writer(&self.0, &mut buf)?;
102		Ok(buf)
103	}
104
105	/// Attempts to serialize the given value as [YAML](https://yaml.org).
106	///
107	/// # Errors
108	///
109	/// See [`serde_yaml::to_vec`].
110	#[cfg(feature = "yaml")]
111	#[inline]
112	pub fn to_yaml(&self) -> Result<String, serde_yaml::Error> {
113		serde_yaml::to_string(&self.0)
114	}
115
116	/// Attempts to serialize the given value as [TOML](https://toml.io).
117	///
118	/// # Errors
119	///
120	/// See [`toml::to_string`].
121	#[cfg(feature = "toml")]
122	#[inline]
123	pub fn to_toml(&self) -> Result<String, toml::ser::Error> {
124		toml::to_string(&self.0)
125	}
126}
127
128impl<T> Codec<T> {
129	/// Attempts to serialize the given value as [Bincode]()
130	///
131	/// # Errors
132	///
133	/// See [`bincode::serialize`].
134	#[cfg(feature = "bincode")]
135	#[inline]
136	pub fn to_bincode(&self) -> Result<Vec<u8>, bincode::error::EncodeError>
137	where
138		T: bincode::Encode,
139	{
140		bincode::encode_to_vec(&self.0, bincode::config::standard())
141	}
142
143	/// Attempts to serialize the given value as [Bitcode]()
144	///
145	/// # Errors
146	///
147	/// See [`bitcode::encode`].
148	#[cfg(feature = "bitcode")]
149	#[inline]
150	pub fn to_bitcode(&self) -> Vec<u8>
151	where
152		T: bitcode::Encode,
153	{
154		bitcode::encode(&self.0)
155	}
156
157	/// Attempts to serialize the given value as the specified [`ContentType`].
158	///
159	/// # Errors
160	///
161	/// See [`Error`].
162	pub fn to_bytes(&self, content_type: ContentType) -> Result<Vec<u8>, Error>
163	where
164		T: CodecEncode,
165	{
166		Ok(match content_type {
167			#[cfg(feature = "json")]
168			ContentType::Json => self.to_json()?,
169			#[cfg(feature = "form")]
170			ContentType::Form => self.to_form()?,
171			#[cfg(feature = "msgpack")]
172			ContentType::MsgPack => self.to_msgpack()?,
173			#[cfg(feature = "bincode")]
174			ContentType::Bincode => self.to_bincode()?,
175			#[cfg(feature = "bitcode")]
176			ContentType::Bitcode => self.to_bitcode(),
177			#[cfg(feature = "cbor")]
178			ContentType::Cbor => self.to_cbor()?,
179			#[cfg(feature = "yaml")]
180			ContentType::Yaml => self.to_yaml()?.into_bytes(),
181			#[cfg(feature = "toml")]
182			ContentType::Toml => self.to_toml()?.into_bytes(),
183		})
184	}
185}