1#[doc(hidden)]
3#[macro_export]
4macro_rules! encode_with_extensions {
5 ($mode:ident) => {
6 #[inline]
9 pub fn encode<W, T>(self, writer: W, value: &T) -> Result<(), Error>
10 where
11 W: Writer,
12 T: ?Sized + Encode<$mode>,
13 {
14 let mut buf = $crate::exports::allocator::buffer();
15 let alloc = $crate::exports::allocator::new(&mut buf);
16 let cx = $crate::exports::context::Same::new(&alloc);
17 self.encode_with(&cx, writer, value)
18 }
19
20 #[cfg(feature = "std")]
23 #[inline]
24 pub fn to_writer<W, T>(self, write: W, value: &T) -> Result<(), Error>
25 where
26 W: io::Write,
27 T: ?Sized + Encode<$mode>,
28 {
29 let writer = $crate::exports::wrap::wrap(write);
30 self.encode(writer, value)
31 }
32
33 #[cfg(feature = "std")]
36 #[inline]
37 pub fn to_writer_with<C, W, T>(self, cx: &C, write: W, value: &T) -> Result<(), C::Error>
38 where
39 C: ?Sized + Context<Mode = $mode>,
40 W: io::Write,
41 T: ?Sized + Encode<$mode>,
42 {
43 let writer = $crate::exports::wrap::wrap(write);
44 self.encode_with(cx, writer, value)
45 }
46
47 #[cfg(feature = "alloc")]
49 #[inline]
50 pub fn to_vec<T>(self, value: &T) -> Result<Vec<u8>, Error>
51 where
52 T: ?Sized + Encode<$mode>,
53 {
54 let mut vec = Vec::new();
55 self.encode(&mut vec, value)?;
56 Ok(vec)
57 }
58
59 #[cfg(feature = "alloc")]
64 #[inline]
65 pub fn to_vec_with<C, T>(self, cx: &C, value: &T) -> Result<Vec<u8>, C::Error>
66 where
67 C: ?Sized + Context<Mode = $mode>,
68 T: ?Sized + Encode<$mode>,
69 {
70 let mut vec = Vec::new();
71 self.encode_with(cx, &mut vec, value)?;
72 Ok(vec)
73 }
74
75 #[inline]
78 pub fn to_fixed_bytes<const N: usize, T>(self, value: &T) -> Result<FixedBytes<N>, Error>
79 where
80 T: ?Sized + Encode<$mode>,
81 {
82 let mut buf = $crate::exports::allocator::buffer();
83 let alloc = $crate::exports::allocator::new(&mut buf);
84 let cx = $crate::exports::context::Same::new(&alloc);
85 self.to_fixed_bytes_with(&cx, value)
86 }
87
88 #[inline]
91 pub fn to_fixed_bytes_with<C, const N: usize, T>(
92 self,
93 cx: &C,
94 value: &T,
95 ) -> Result<FixedBytes<N>, C::Error>
96 where
97 C: ?Sized + Context<Mode = $mode>,
98 T: ?Sized + Encode<$mode>,
99 {
100 let mut bytes = FixedBytes::new();
101 self.encode_with(cx, &mut bytes, value)?;
102 Ok(bytes)
103 }
104 };
105}
106
107#[doc(hidden)]
109#[macro_export]
110macro_rules! encoding_from_slice_impls {
111 ($mode:ident, $decoder_new:path) => {
112 #[inline]
115 pub fn from_slice<'de, T>(self, bytes: &'de [u8]) -> Result<T, Error>
116 where
117 T: Decode<'de, $mode>,
118 {
119 let mut buf = $crate::exports::allocator::buffer();
120 let alloc = $crate::exports::allocator::new(&mut buf);
121 let cx = $crate::exports::context::Same::new(&alloc);
122 self.from_slice_with(&cx, bytes)
123 }
124
125 #[inline]
131 pub fn from_slice_with<'de, C, T>(self, cx: &C, bytes: &'de [u8]) -> Result<T, C::Error>
132 where
133 C: ?Sized + Context<Mode = $mode>,
134 T: Decode<'de, $mode>,
135 {
136 let reader = SliceReader::new(bytes);
137 self.decode_with(cx, reader)
138 }
139 };
140}
141
142#[doc(hidden)]
144#[macro_export]
145macro_rules! encoding_impls {
146 ($mode:ident, $encoder_new:path, $decoder_new:path) => {
147 #[inline]
153 pub fn encode_with<C, W, T>(self, cx: &C, writer: W, value: &T) -> Result<(), C::Error>
154 where
155 C: ?Sized + Context<Mode = $mode>,
156 W: Writer,
157 T: ?Sized + Encode<$mode>,
158 {
159 T::encode(value, cx, $encoder_new(cx, writer))
160 }
161
162 #[inline]
168 pub fn decode_with<'de, C, R, T>(self, cx: &C, reader: R) -> Result<T, C::Error>
169 where
170 C: ?Sized + Context<Mode = $mode>,
171 R: Reader<'de>,
172 T: Decode<'de, $mode>,
173 {
174 T::decode(cx, $decoder_new(cx, reader))
175 }
176
177 #[inline]
180 pub fn decode<'de, R, T>(self, reader: R) -> Result<T, Error>
181 where
182 R: Reader<'de>,
183 T: Decode<'de, $mode>,
184 {
185 let mut buf = $crate::exports::allocator::buffer();
186 let alloc = $crate::exports::allocator::new(&mut buf);
187 let cx = $crate::exports::context::Same::new(&alloc);
188 self.decode_with(&cx, reader)
189 }
190
191 $crate::encode_with_extensions!($mode);
192 };
193}
194
195#[doc(hidden)]
196#[macro_export]
197macro_rules! test_include_if {
198 (#[musli_value] => $($rest:tt)*) => { $($rest)* };
199 (=> $($_:tt)*) => {};
200}
201
202#[doc(hidden)]
204#[macro_export]
205#[allow(clippy::crate_in_macro_def)]
206macro_rules! test_fns {
207 ($what:expr $(, $(#[$option:ident])*)?) => {
208 #[doc(hidden)]
210 #[track_caller]
211 #[cfg(feature = "test")]
212 pub fn rt<T>(value: T) -> T
213 where
214 T: ::musli::en::Encode + ::musli::de::DecodeOwned + ::core::fmt::Debug + ::core::cmp::PartialEq,
215 {
216 const WHAT: &str = $what;
217 const ENCODING: crate::Encoding = crate::Encoding::new();
218
219 use ::core::any::type_name;
220 use ::alloc::string::ToString;
221
222 struct FormatBytes<'a>(&'a [u8]);
223
224 impl ::core::fmt::Display for FormatBytes<'_> {
225 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
226 write!(f, "b\"")?;
227
228 for b in self.0 {
229 if b.is_ascii_graphic() {
230 write!(f, "{}", *b as char)?;
231 } else {
232 write!(f, "\\x{b:02x}")?;
233 }
234 }
235
236 write!(f, "\"")?;
237 Ok(())
238 }
239 }
240
241 let format_error = |cx: &crate::context::SystemContext<_, _>| {
242 use ::alloc::vec::Vec;
243
244 let mut errors = Vec::new();
245
246 for error in cx.errors() {
247 errors.push(error.to_string());
248 }
249
250 errors.join("\n")
251 };
252
253 let mut buf = crate::allocator::buffer();
254 let alloc = crate::allocator::new(&mut buf);
255 let mut cx = crate::context::SystemContext::new(&alloc);
256 cx.include_type();
257
258 let out = match ENCODING.to_vec_with(&cx, &value) {
259 Ok(out) => out,
260 Err(..) => {
261 let error = format_error(&cx);
262 panic!("{WHAT}: {}: failed to encode:\n{error}", type_name::<T>())
263 }
264 };
265
266 $crate::test_include_if! {
267 $($(#[$option])*)* =>
268 let value_decode: ::musli_value::Value = match ENCODING.from_slice_with(&cx, out.as_slice()) {
269 Ok(decoded) => decoded,
270 Err(..) => {
271 let out = FormatBytes(&out);
272 let error = format_error(&cx);
273 panic!("{WHAT}: {}: failed to decode to value type:\nBytes:{out}\n{error}", type_name::<T>())
274 }
275 };
276
277 let value_decoded: T = match ::musli_value::decode_with(&cx, &value_decode) {
278 Ok(decoded) => decoded,
279 Err(..) => {
280 let out = FormatBytes(&out);
281 let error = format_error(&cx);
282 panic!("{WHAT}: {}: failed to decode from value type:\nBytes: {out}\nValue: {value_decode:?}\n{error}", type_name::<T>())
283 }
284 };
285
286 assert_eq!(value_decoded, value, "{WHAT}: {}: musli-value roundtrip does not match", type_name::<T>());
287 }
288
289 let decoded: T = match ENCODING.from_slice_with(&cx, out.as_slice()) {
290 Ok(decoded) => decoded,
291 Err(..) => {
292 let out = FormatBytes(&out);
293 let error = format_error(&cx);
294 panic!("{WHAT}: {}: failed to decode:\nBytes: {out}\n{error}", type_name::<T>())
295 }
296 };
297
298 assert_eq!(decoded, value, "{WHAT}: {}: roundtrip does not match", type_name::<T>());
299
300 decoded
301 }
302
303 #[doc(hidden)]
305 #[track_caller]
306 #[cfg(feature = "test")]
307 pub fn decode<'de, T, U>(value: T, out: &'de mut ::alloc::vec::Vec<u8>, _hint: &U) -> U
308 where
309 T: ::musli::en::Encode + ::core::fmt::Debug + ::core::cmp::PartialEq,
310 U: ::musli::de::Decode<'de>,
311 {
312 const WHAT: &str = $what;
313 const ENCODING: crate::Encoding = crate::Encoding::new();
314
315 use ::core::any::type_name;
316 use ::alloc::string::ToString;
317
318 let format_error = |cx: &crate::context::SystemContext<_, _>| {
319 use ::alloc::vec::Vec;
320
321 let mut errors = Vec::new();
322
323 for error in cx.errors() {
324 errors.push(error.to_string());
325 }
326
327 errors.join("\n")
328 };
329
330 let mut buf = crate::allocator::buffer();
331 let alloc = crate::allocator::new(&mut buf);
332 let mut cx = crate::context::SystemContext::new(&alloc);
333 cx.include_type();
334
335 out.clear();
336
337 match ENCODING.to_writer_with(&cx, &mut *out, &value) {
338 Ok(()) => (),
339 Err(..) => {
340 let error = format_error(&cx);
341 panic!("{WHAT}: {}: failed to encode:\n{error}", type_name::<T>())
342 }
343 };
344
345 match ENCODING.from_slice_with(&cx, out) {
346 Ok(decoded) => decoded,
347 Err(error) => {
348 let error = format_error(&cx);
349 panic!("{WHAT}: {}: failed to decode:\n{error}", type_name::<T>())
350 }
351 }
352 }
353
354 #[doc(hidden)]
356 #[track_caller]
357 #[cfg(feature = "test")]
358 pub fn to_vec<T>(value: T) -> ::alloc::vec::Vec<u8>
359 where
360 T: ::musli::en::Encode,
361 {
362 const WHAT: &str = $what;
363 const ENCODING: crate::Encoding = crate::Encoding::new();
364
365 use ::core::any::type_name;
366 use ::alloc::string::ToString;
367
368 let format_error = |cx: &crate::context::SystemContext<_, _>| {
369 use ::alloc::vec::Vec;
370
371 let mut errors = Vec::new();
372
373 for error in cx.errors() {
374 errors.push(error.to_string());
375 }
376
377 errors.join("\n")
378 };
379
380 let mut buf = crate::allocator::buffer();
381 let alloc = crate::allocator::new(&mut buf);
382 let mut cx = crate::context::SystemContext::new(&alloc);
383 cx.include_type();
384
385 match ENCODING.to_vec_with(&cx, &value) {
386 Ok(out) => out,
387 Err(..) => {
388 let error = format_error(&cx);
389 panic!("{WHAT}: {}: failed to encode:\n{error}", type_name::<T>())
390 }
391 }
392 }
393 }
394}