1use crate::PlatformVersionEncode;
2
3use bincode::enc::Encoder;
4use bincode::error::EncodeError;
5use bincode::Encode;
6use core::{
7 cell::{Cell, RefCell},
8 marker::PhantomData,
9 num::{
10 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
11 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
12 },
13 ops::{Bound, Range, RangeInclusive},
14 time::Duration,
15};
16use platform_version::version::PlatformVersion;
17
18impl PlatformVersionEncode for () {
19 fn platform_encode<E: Encoder>(
20 &self,
21 _: &mut E,
22 _: &PlatformVersion,
23 ) -> Result<(), EncodeError> {
24 Ok(())
25 }
26}
27
28impl<T> PlatformVersionEncode for PhantomData<T> {
29 fn platform_encode<E: Encoder>(
30 &self,
31 _: &mut E,
32 _: &PlatformVersion,
33 ) -> Result<(), EncodeError> {
34 Ok(())
35 }
36}
37
38impl PlatformVersionEncode for bool {
39 fn platform_encode<E: Encoder>(
40 &self,
41 encoder: &mut E,
42 _: &PlatformVersion,
43 ) -> Result<(), EncodeError> {
44 Encode::encode(self, encoder)
45 }
46}
47
48impl PlatformVersionEncode for u8 {
49 fn platform_encode<E: Encoder>(
50 &self,
51 encoder: &mut E,
52 _: &PlatformVersion,
53 ) -> Result<(), EncodeError> {
54 Encode::encode(self, encoder)
55 }
56}
57
58impl PlatformVersionEncode for NonZeroU8 {
59 fn platform_encode<E: Encoder>(
60 &self,
61 encoder: &mut E,
62 _: &PlatformVersion,
63 ) -> Result<(), EncodeError> {
64 Encode::encode(self, encoder)
65 }
66}
67
68impl PlatformVersionEncode for u16 {
69 fn platform_encode<E: Encoder>(
70 &self,
71 encoder: &mut E,
72 _: &PlatformVersion,
73 ) -> Result<(), EncodeError> {
74 Encode::encode(self, encoder)
75 }
76}
77
78impl PlatformVersionEncode for NonZeroU16 {
79 fn platform_encode<E: Encoder>(
80 &self,
81 encoder: &mut E,
82 _: &PlatformVersion,
83 ) -> Result<(), EncodeError> {
84 Encode::encode(self, encoder)
85 }
86}
87
88impl PlatformVersionEncode for u32 {
89 fn platform_encode<E: Encoder>(
90 &self,
91 encoder: &mut E,
92 _: &PlatformVersion,
93 ) -> Result<(), EncodeError> {
94 Encode::encode(self, encoder)
95 }
96}
97
98impl PlatformVersionEncode for NonZeroU32 {
99 fn platform_encode<E: Encoder>(
100 &self,
101 encoder: &mut E,
102 _: &PlatformVersion,
103 ) -> Result<(), EncodeError> {
104 Encode::encode(self, encoder)
105 }
106}
107
108impl PlatformVersionEncode for u64 {
109 fn platform_encode<E: Encoder>(
110 &self,
111 encoder: &mut E,
112 _: &PlatformVersion,
113 ) -> Result<(), EncodeError> {
114 Encode::encode(self, encoder)
115 }
116}
117
118impl PlatformVersionEncode for NonZeroU64 {
119 fn platform_encode<E: Encoder>(
120 &self,
121 encoder: &mut E,
122 _: &PlatformVersion,
123 ) -> Result<(), EncodeError> {
124 Encode::encode(self, encoder)
125 }
126}
127
128impl PlatformVersionEncode for u128 {
129 fn platform_encode<E: Encoder>(
130 &self,
131 encoder: &mut E,
132 _: &PlatformVersion,
133 ) -> Result<(), EncodeError> {
134 Encode::encode(self, encoder)
135 }
136}
137
138impl PlatformVersionEncode for NonZeroU128 {
139 fn platform_encode<E: Encoder>(
140 &self,
141 encoder: &mut E,
142 _: &PlatformVersion,
143 ) -> Result<(), EncodeError> {
144 Encode::encode(self, encoder)
145 }
146}
147
148impl PlatformVersionEncode for usize {
149 fn platform_encode<E: Encoder>(
150 &self,
151 encoder: &mut E,
152 _: &PlatformVersion,
153 ) -> Result<(), EncodeError> {
154 Encode::encode(self, encoder)
155 }
156}
157
158impl PlatformVersionEncode for NonZeroUsize {
159 fn platform_encode<E: Encoder>(
160 &self,
161 encoder: &mut E,
162 _: &PlatformVersion,
163 ) -> Result<(), EncodeError> {
164 Encode::encode(self, encoder)
165 }
166}
167
168impl PlatformVersionEncode for i8 {
169 fn platform_encode<E: Encoder>(
170 &self,
171 encoder: &mut E,
172 _: &PlatformVersion,
173 ) -> Result<(), EncodeError> {
174 Encode::encode(self, encoder)
175 }
176}
177
178impl PlatformVersionEncode for NonZeroI8 {
179 fn platform_encode<E: Encoder>(
180 &self,
181 encoder: &mut E,
182 _: &PlatformVersion,
183 ) -> Result<(), EncodeError> {
184 Encode::encode(self, encoder)
185 }
186}
187
188impl PlatformVersionEncode for i16 {
189 fn platform_encode<E: Encoder>(
190 &self,
191 encoder: &mut E,
192 _: &PlatformVersion,
193 ) -> Result<(), EncodeError> {
194 Encode::encode(self, encoder)
195 }
196}
197
198impl PlatformVersionEncode for NonZeroI16 {
199 fn platform_encode<E: Encoder>(
200 &self,
201 encoder: &mut E,
202 _: &PlatformVersion,
203 ) -> Result<(), EncodeError> {
204 Encode::encode(self, encoder)
205 }
206}
207
208impl PlatformVersionEncode for i32 {
209 fn platform_encode<E: Encoder>(
210 &self,
211 encoder: &mut E,
212 _: &PlatformVersion,
213 ) -> Result<(), EncodeError> {
214 Encode::encode(self, encoder)
215 }
216}
217
218impl PlatformVersionEncode for NonZeroI32 {
219 fn platform_encode<E: Encoder>(
220 &self,
221 encoder: &mut E,
222 _: &PlatformVersion,
223 ) -> Result<(), EncodeError> {
224 Encode::encode(self, encoder)
225 }
226}
227
228impl PlatformVersionEncode for i64 {
229 fn platform_encode<E: Encoder>(
230 &self,
231 encoder: &mut E,
232 _: &PlatformVersion,
233 ) -> Result<(), EncodeError> {
234 Encode::encode(self, encoder)
235 }
236}
237
238impl PlatformVersionEncode for NonZeroI64 {
239 fn platform_encode<E: Encoder>(
240 &self,
241 encoder: &mut E,
242 _: &PlatformVersion,
243 ) -> Result<(), EncodeError> {
244 Encode::encode(self, encoder)
245 }
246}
247
248impl PlatformVersionEncode for i128 {
249 fn platform_encode<E: Encoder>(
250 &self,
251 encoder: &mut E,
252 _: &PlatformVersion,
253 ) -> Result<(), EncodeError> {
254 Encode::encode(self, encoder)
255 }
256}
257
258impl PlatformVersionEncode for NonZeroI128 {
259 fn platform_encode<E: Encoder>(
260 &self,
261 encoder: &mut E,
262 _: &PlatformVersion,
263 ) -> Result<(), EncodeError> {
264 Encode::encode(self, encoder)
265 }
266}
267
268impl PlatformVersionEncode for isize {
269 fn platform_encode<E: Encoder>(
270 &self,
271 encoder: &mut E,
272 _: &PlatformVersion,
273 ) -> Result<(), EncodeError> {
274 Encode::encode(self, encoder)
275 }
276}
277
278impl PlatformVersionEncode for NonZeroIsize {
279 fn platform_encode<E: Encoder>(
280 &self,
281 encoder: &mut E,
282 _: &PlatformVersion,
283 ) -> Result<(), EncodeError> {
284 Encode::encode(self, encoder)
285 }
286}
287
288impl PlatformVersionEncode for f32 {
289 fn platform_encode<E: Encoder>(
290 &self,
291 encoder: &mut E,
292 _: &PlatformVersion,
293 ) -> Result<(), EncodeError> {
294 Encode::encode(self, encoder)
295 }
296}
297
298impl PlatformVersionEncode for f64 {
299 fn platform_encode<E: Encoder>(
300 &self,
301 encoder: &mut E,
302 _: &PlatformVersion,
303 ) -> Result<(), EncodeError> {
304 Encode::encode(self, encoder)
305 }
306}
307
308impl PlatformVersionEncode for char {
309 fn platform_encode<E: Encoder>(
310 &self,
311 encoder: &mut E,
312 _: &PlatformVersion,
313 ) -> Result<(), EncodeError> {
314 Encode::encode(self, encoder)
315 }
316}
317
318impl<T> PlatformVersionEncode for [T]
329where
330 T: PlatformVersionEncode + Encode + 'static,
331{
332 fn platform_encode<E: Encoder>(
333 &self,
334 encoder: &mut E,
335 platform_version: &PlatformVersion,
336 ) -> Result<(), EncodeError> {
337 super::encode_slice_len(encoder, self.len())?;
338
339 if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
340 return Encode::encode(self, encoder);
341 }
342
343 for item in self {
344 item.platform_encode(encoder, platform_version)?;
345 }
346 Ok(())
347 }
348}
349
350impl PlatformVersionEncode for str {
351 fn platform_encode<E: Encoder>(
352 &self,
353 encoder: &mut E,
354 _: &PlatformVersion,
355 ) -> Result<(), EncodeError> {
356 Encode::encode(self, encoder)
357 }
358}
359
360impl<T, const N: usize> PlatformVersionEncode for [T; N]
361where
362 T: PlatformVersionEncode,
363{
364 fn platform_encode<E: Encoder>(
365 &self,
366 encoder: &mut E,
367 platform_version: &PlatformVersion,
368 ) -> Result<(), EncodeError> {
369 for item in self.iter() {
370 item.platform_encode(encoder, platform_version)?;
371 }
372 Ok(())
373 }
374}
375
376impl<T> PlatformVersionEncode for Option<T>
377where
378 T: PlatformVersionEncode,
379{
380 fn platform_encode<E: Encoder>(
381 &self,
382 encoder: &mut E,
383 platform_version: &PlatformVersion,
384 ) -> Result<(), EncodeError> {
385 super::encode_option_variant(encoder, self)?;
386 if let Some(val) = self {
387 val.platform_encode(encoder, platform_version)?;
388 }
389 Ok(())
390 }
391}
392
393impl<T, U> PlatformVersionEncode for Result<T, U>
394where
395 T: PlatformVersionEncode,
396 U: PlatformVersionEncode,
397{
398 fn platform_encode<E: Encoder>(
399 &self,
400 encoder: &mut E,
401 platform_version: &PlatformVersion,
402 ) -> Result<(), EncodeError> {
403 match self {
404 Ok(val) => {
405 0u32.platform_encode(encoder, platform_version)?;
406 val.platform_encode(encoder, platform_version)
407 }
408 Err(err) => {
409 1u32.platform_encode(encoder, platform_version)?;
410 err.platform_encode(encoder, platform_version)
411 }
412 }
413 }
414}
415
416impl<T> PlatformVersionEncode for Cell<T>
417where
418 T: PlatformVersionEncode + Copy,
419{
420 fn platform_encode<E: Encoder>(
421 &self,
422 encoder: &mut E,
423 platform_version: &PlatformVersion,
424 ) -> Result<(), EncodeError> {
425 T::platform_encode(&self.get(), encoder, platform_version)
426 }
427}
428
429impl<T> PlatformVersionEncode for RefCell<T>
430where
431 T: PlatformVersionEncode + ?Sized,
432{
433 fn platform_encode<E: Encoder>(
434 &self,
435 encoder: &mut E,
436 platform_version: &PlatformVersion,
437 ) -> Result<(), EncodeError> {
438 let borrow_guard = self
439 .try_borrow()
440 .map_err(|e| EncodeError::RefCellAlreadyBorrowed {
441 inner: e,
442 type_name: core::any::type_name::<RefCell<T>>(),
443 })?;
444 T::platform_encode(&borrow_guard, encoder, platform_version)
445 }
446}
447
448impl PlatformVersionEncode for Duration {
449 fn platform_encode<E: Encoder>(
450 &self,
451 encoder: &mut E,
452 _: &PlatformVersion,
453 ) -> Result<(), EncodeError> {
454 Encode::encode(self, encoder)
455 }
456}
457
458impl<T> PlatformVersionEncode for Range<T>
459where
460 T: Encode,
461{
462 fn platform_encode<E: Encoder>(
463 &self,
464 encoder: &mut E,
465 _: &PlatformVersion,
466 ) -> Result<(), EncodeError> {
467 Encode::encode(self, encoder)
468 }
469}
470
471impl<T> PlatformVersionEncode for RangeInclusive<T>
472where
473 T: Encode,
474{
475 fn platform_encode<E: Encoder>(
476 &self,
477 encoder: &mut E,
478 _: &PlatformVersion,
479 ) -> Result<(), EncodeError> {
480 Encode::encode(self, encoder)
481 }
482}
483
484impl<T> PlatformVersionEncode for Bound<T>
485where
486 T: Encode,
487{
488 fn platform_encode<E: Encoder>(
489 &self,
490 encoder: &mut E,
491 _: &PlatformVersion,
492 ) -> Result<(), EncodeError> {
493 Encode::encode(self, encoder)
494 }
495}
496
497impl<T> PlatformVersionEncode for &T
498where
499 T: PlatformVersionEncode + ?Sized,
500{
501 fn platform_encode<E: Encoder>(
502 &self,
503 encoder: &mut E,
504 platform_version: &PlatformVersion,
505 ) -> Result<(), EncodeError> {
506 T::platform_encode(self, encoder, platform_version)
507 }
508}
509
510impl<A> PlatformVersionEncode for (A,)
511where
512 A: PlatformVersionEncode,
513{
514 fn platform_encode<_E: Encoder>(
515 &self,
516 encoder: &mut _E,
517 platform_version: &PlatformVersion,
518 ) -> Result<(), EncodeError> {
519 self.0.platform_encode(encoder, platform_version)?;
520 Ok(())
521 }
522}
523
524impl<A, B> PlatformVersionEncode for (A, B)
525where
526 A: PlatformVersionEncode,
527 B: PlatformVersionEncode,
528{
529 fn platform_encode<_E: Encoder>(
530 &self,
531 encoder: &mut _E,
532 platform_version: &PlatformVersion,
533 ) -> Result<(), EncodeError> {
534 self.0.platform_encode(encoder, platform_version)?;
535 self.1.platform_encode(encoder, platform_version)?;
536 Ok(())
537 }
538}
539
540impl<A, B, C> PlatformVersionEncode for (A, B, C)
541where
542 A: PlatformVersionEncode,
543 B: PlatformVersionEncode,
544 C: PlatformVersionEncode,
545{
546 fn platform_encode<_E: Encoder>(
547 &self,
548 encoder: &mut _E,
549 platform_version: &PlatformVersion,
550 ) -> Result<(), EncodeError> {
551 self.0.platform_encode(encoder, platform_version)?;
552 self.1.platform_encode(encoder, platform_version)?;
553 self.2.platform_encode(encoder, platform_version)?;
554 Ok(())
555 }
556}
557
558impl<A, B, C, D> PlatformVersionEncode for (A, B, C, D)
559where
560 A: PlatformVersionEncode,
561 B: PlatformVersionEncode,
562 C: PlatformVersionEncode,
563 D: PlatformVersionEncode,
564{
565 fn platform_encode<_E: Encoder>(
566 &self,
567 encoder: &mut _E,
568 platform_version: &PlatformVersion,
569 ) -> Result<(), EncodeError> {
570 self.0.platform_encode(encoder, platform_version)?;
571 self.1.platform_encode(encoder, platform_version)?;
572 self.2.platform_encode(encoder, platform_version)?;
573 self.3.platform_encode(encoder, platform_version)?;
574 Ok(())
575 }
576}
577
578impl<A, B, C, D, E> PlatformVersionEncode for (A, B, C, D, E)
579where
580 A: PlatformVersionEncode,
581 B: PlatformVersionEncode,
582 C: PlatformVersionEncode,
583 D: PlatformVersionEncode,
584 E: PlatformVersionEncode,
585{
586 fn platform_encode<_E: Encoder>(
587 &self,
588 encoder: &mut _E,
589 platform_version: &PlatformVersion,
590 ) -> Result<(), EncodeError> {
591 self.0.platform_encode(encoder, platform_version)?;
592 self.1.platform_encode(encoder, platform_version)?;
593 self.2.platform_encode(encoder, platform_version)?;
594 self.3.platform_encode(encoder, platform_version)?;
595 self.4.platform_encode(encoder, platform_version)?;
596 Ok(())
597 }
598}
599
600#[cfg(test)]
601#[allow(clippy::needless_borrows_for_generic_args)]
602mod tests {
603 use super::*;
604 use bincode::config;
605 use platform_version::version::PlatformVersion;
606
607 fn cfg() -> impl bincode::config::Config {
608 config::standard().with_big_endian().with_no_limit()
609 }
610
611 fn pv() -> &'static PlatformVersion {
612 PlatformVersion::first()
613 }
614
615 fn round_trip<T>(value: T) -> T
617 where
618 T: PlatformVersionEncode + crate::PlatformVersionedDecode,
619 {
620 let encoded = crate::platform_encode_to_vec(value, cfg(), pv()).unwrap();
621 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap()
622 }
623
624 #[test]
629 fn encode_u8_slice_optimization() {
630 let data: Vec<u8> = vec![1, 2, 3, 4, 5];
632 let encoded = crate::platform_encode_to_vec(&data, cfg(), pv()).unwrap();
633 let decoded: Vec<u8> =
634 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap();
635 assert_eq!(decoded, data);
636 }
637
638 #[test]
639 fn encode_non_u8_slice() {
640 let data: Vec<u32> = vec![100, 200, 300];
642 let encoded = crate::platform_encode_to_vec(&data, cfg(), pv()).unwrap();
643 let decoded: Vec<u32> =
644 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap();
645 assert_eq!(decoded, data);
646 }
647
648 #[test]
649 fn encode_empty_slice() {
650 let data: &[u8] = &[];
651 let encoded = crate::platform_encode_to_vec(data, cfg(), pv()).unwrap();
652 let decoded: Vec<u8> =
653 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap();
654 assert!(decoded.is_empty());
655 }
656
657 #[test]
662 fn encode_array_u32() {
663 let value: [u32; 3] = [10, 20, 30];
664 assert_eq!(round_trip(value), value);
665 }
666
667 #[test]
668 fn encode_array_single_element() {
669 let value: [u64; 1] = [42];
670 assert_eq!(round_trip(value), value);
671 }
672
673 #[test]
678 fn encode_option_some() {
679 let value: Option<i32> = Some(-42);
680 assert_eq!(round_trip(value), value);
681 }
682
683 #[test]
684 fn encode_option_none() {
685 let value: Option<i32> = None;
686 assert_eq!(round_trip(value), value);
687 }
688
689 #[test]
694 fn encode_result_ok() {
695 let value: Result<u32, u8> = Ok(42);
696 assert_eq!(round_trip(value), value);
697 }
698
699 #[test]
700 fn encode_result_err() {
701 let value: Result<u32, u8> = Err(1);
702 assert_eq!(round_trip(value), value);
703 }
704
705 #[test]
710 fn encode_cell() {
711 let value = Cell::new(77u32);
712 let encoded = crate::platform_encode_to_vec(&value, cfg(), pv()).unwrap();
713 let decoded: u32 =
714 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap();
715 assert_eq!(decoded, 77);
716 }
717
718 #[test]
719 fn encode_refcell() {
720 let value = RefCell::new(88u16);
721 let encoded = crate::platform_encode_to_vec(&value, cfg(), pv()).unwrap();
722 let decoded: u16 =
723 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap();
724 assert_eq!(decoded, 88);
725 }
726
727 #[test]
728 fn encode_refcell_already_borrowed_returns_error() {
729 let value = RefCell::new(42u32);
730 let _borrow = value.borrow_mut(); let result = crate::platform_encode_to_vec(&value, cfg(), pv());
732 assert!(result.is_err());
733 }
734
735 #[test]
740 fn encode_str() {
741 let value = "hello platform";
742 let encoded = crate::platform_encode_to_vec(value, cfg(), pv()).unwrap();
743 let decoded: String =
744 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap();
745 assert_eq!(decoded, value);
746 }
747
748 #[test]
753 fn encode_ref() {
754 let value: u32 = 42;
755 let encoded = crate::platform_encode_to_vec(&value, cfg(), pv()).unwrap();
756 let decoded: u32 =
757 crate::platform_versioned_decode_from_slice(&encoded, cfg(), pv()).unwrap();
758 assert_eq!(decoded, value);
759 }
760
761 #[test]
766 fn encode_tuple_1() {
767 let value: (u32,) = (42,);
768 assert_eq!(round_trip(value), value);
769 }
770
771 #[test]
772 fn encode_tuple_2() {
773 let value: (u32, i8) = (42, -1);
774 assert_eq!(round_trip(value), value);
775 }
776
777 #[test]
778 fn encode_tuple_3() {
779 let value: (u8, u16, u32) = (1, 2, 3);
780 assert_eq!(round_trip(value), value);
781 }
782
783 #[test]
784 fn encode_tuple_4() {
785 let value: (u8, u16, u32, u64) = (1, 2, 3, 4);
786 assert_eq!(round_trip(value), value);
787 }
788
789 #[test]
790 fn encode_tuple_5() {
791 let value: (u8, u16, u32, u64, bool) = (1, 2, 3, 4, true);
792 assert_eq!(round_trip(value), value);
793 }
794
795 #[test]
800 fn encode_duration() {
801 let value = Duration::new(60, 500_000_000);
802 assert_eq!(round_trip(value), value);
803 }
804
805 #[test]
806 fn encode_range() {
807 let value = 10u32..20u32;
808 assert_eq!(round_trip(value.clone()), value);
809 }
810
811 #[test]
812 fn encode_range_inclusive() {
813 let value = 10u32..=20u32;
814 assert_eq!(round_trip(value.clone()), value);
815 }
816
817 #[test]
818 fn encode_bound_unbounded() {
819 use core::ops::Bound;
820 let value: Bound<u32> = Bound::Unbounded;
821 assert_eq!(round_trip(value), value);
822 }
823
824 #[test]
825 fn encode_bound_included() {
826 use core::ops::Bound;
827 let value: Bound<u32> = Bound::Included(5);
828 assert_eq!(round_trip(value), value);
829 }
830
831 #[test]
832 fn encode_bound_excluded() {
833 use core::ops::Bound;
834 let value: Bound<u32> = Bound::Excluded(5);
835 assert_eq!(round_trip(value), value);
836 }
837}