1use crate::altrep_traits::{NA_INTEGER, NA_LOGICAL, NA_REAL};
29use crate::ffi::{Rboolean, Rcomplex};
30
31pub trait Coerce<R> {
48 fn coerce(self) -> R;
52}
53
54pub trait TryCoerce<R> {
58 type Error;
60 fn try_coerce(self) -> Result<R, Self::Error>;
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum CoerceError {
67 Overflow,
69 PrecisionLoss,
71 NaN,
73 Zero,
75}
76
77impl std::fmt::Display for CoerceError {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 match self {
80 CoerceError::Overflow => write!(f, "value out of range"),
81 CoerceError::PrecisionLoss => write!(f, "precision loss"),
82 CoerceError::NaN => write!(f, "NaN cannot be converted"),
83 CoerceError::Zero => write!(f, "zero not allowed"),
84 }
85 }
86}
87
88impl std::error::Error for CoerceError {}
89
90impl<T, R> TryCoerce<R> for T
93where
94 T: Coerce<R>,
95{
96 type Error = std::convert::Infallible;
97
98 #[inline(always)]
99 fn try_coerce(self) -> Result<R, Self::Error> {
100 Ok(self.coerce())
101 }
102}
103macro_rules! impl_identity {
112 ($t:ty) => {
113 impl Coerce<$t> for $t {
114 #[inline(always)]
115 fn coerce(self) -> $t {
116 self
117 }
118 }
119 };
120}
121
122impl_identity!(i32);
123impl_identity!(f64);
124impl_identity!(Rboolean);
125impl_identity!(u8);
126impl_identity!(Rcomplex);
127impl<T: crate::markers::WidensToI32> Coerce<i32> for T {
136 #[inline(always)]
137 fn coerce(self) -> i32 {
138 self.into()
139 }
140}
141
142impl<T: crate::markers::WidensToF64> Coerce<f64> for T {
147 #[inline(always)]
148 fn coerce(self) -> f64 {
149 self.into()
150 }
151}
152impl Coerce<i64> for u8 {
157 #[inline(always)]
158 fn coerce(self) -> i64 {
159 self.into()
160 }
161}
162
163impl Coerce<isize> for u8 {
164 #[inline(always)]
165 fn coerce(self) -> isize {
166 self.into()
167 }
168}
169
170impl Coerce<u64> for u8 {
171 #[inline(always)]
172 fn coerce(self) -> u64 {
173 self.into()
174 }
175}
176
177impl Coerce<usize> for u8 {
178 #[inline(always)]
179 fn coerce(self) -> usize {
180 self.into()
181 }
182}
183
184impl Coerce<f32> for u8 {
185 #[inline(always)]
186 fn coerce(self) -> f32 {
187 self.into()
188 }
189}
190
191impl Coerce<f32> for i32 {
192 #[inline(always)]
193 fn coerce(self) -> f32 {
194 self as f32
195 }
196}
197impl Coerce<Rboolean> for bool {
202 #[inline(always)]
203 fn coerce(self) -> Rboolean {
204 if self {
205 Rboolean::TRUE
206 } else {
207 Rboolean::FALSE
208 }
209 }
210}
211
212impl Coerce<i32> for bool {
213 #[inline(always)]
214 fn coerce(self) -> i32 {
215 if self { 1 } else { 0 }
216 }
217}
218
219impl Coerce<f64> for bool {
220 #[inline(always)]
221 fn coerce(self) -> f64 {
222 if self { 1.0 } else { 0.0 }
223 }
224}
225
226impl Coerce<i32> for Rboolean {
227 #[inline(always)]
228 fn coerce(self) -> i32 {
229 self as i32
230 }
231}
232impl Coerce<f64> for Option<f64> {
238 #[inline(always)]
239 fn coerce(self) -> f64 {
240 self.unwrap_or(NA_REAL)
241 }
242}
243
244impl Coerce<i32> for Option<i32> {
246 #[inline(always)]
247 fn coerce(self) -> i32 {
248 self.unwrap_or(NA_INTEGER)
249 }
250}
251
252impl Coerce<i32> for Option<bool> {
254 #[inline(always)]
255 fn coerce(self) -> i32 {
256 match self {
257 Some(true) => 1,
258 Some(false) => 0,
259 None => NA_LOGICAL,
260 }
261 }
262}
263
264impl Coerce<i32> for Option<Rboolean> {
266 #[inline(always)]
267 fn coerce(self) -> i32 {
268 match self {
269 Some(v) => v as i32,
270 None => NA_LOGICAL,
271 }
272 }
273}
274impl Coerce<i64> for i32 {
280 #[inline(always)]
281 fn coerce(self) -> i64 {
282 self.into()
283 }
284}
285
286impl Coerce<isize> for i32 {
288 #[inline(always)]
289 fn coerce(self) -> isize {
290 self as isize
291 }
292}
293
294impl TryCoerce<u32> for i32 {
296 type Error = CoerceError;
297
298 #[inline]
299 fn try_coerce(self) -> Result<u32, CoerceError> {
300 self.try_into().map_err(|_| CoerceError::Overflow)
301 }
302}
303
304impl TryCoerce<u64> for i32 {
306 type Error = CoerceError;
307
308 #[inline]
309 fn try_coerce(self) -> Result<u64, CoerceError> {
310 self.try_into().map_err(|_| CoerceError::Overflow)
311 }
312}
313
314impl TryCoerce<usize> for i32 {
316 type Error = CoerceError;
317
318 #[inline]
319 fn try_coerce(self) -> Result<usize, CoerceError> {
320 self.try_into().map_err(|_| CoerceError::Overflow)
321 }
322}
323use core::num::{
328 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32,
329 NonZeroU64, NonZeroUsize,
330};
331
332macro_rules! impl_nonzero_from_self {
333 ($base:ty, $nz:ty) => {
334 impl TryCoerce<$nz> for $base {
335 type Error = CoerceError;
336
337 #[inline]
338 fn try_coerce(self) -> Result<$nz, CoerceError> {
339 <$nz>::new(self).ok_or(CoerceError::Zero)
340 }
341 }
342 };
343}
344
345impl_nonzero_from_self!(i8, NonZeroI8);
347impl_nonzero_from_self!(i16, NonZeroI16);
348impl_nonzero_from_self!(i32, NonZeroI32);
349impl_nonzero_from_self!(i64, NonZeroI64);
350impl_nonzero_from_self!(isize, NonZeroIsize);
351impl_nonzero_from_self!(u8, NonZeroU8);
352impl_nonzero_from_self!(u16, NonZeroU16);
353impl_nonzero_from_self!(u32, NonZeroU32);
354impl_nonzero_from_self!(u64, NonZeroU64);
355impl_nonzero_from_self!(usize, NonZeroUsize);
356
357impl TryCoerce<NonZeroI64> for i32 {
359 type Error = CoerceError;
360
361 #[inline]
362 fn try_coerce(self) -> Result<NonZeroI64, CoerceError> {
363 NonZeroI64::new(self.into()).ok_or(CoerceError::Zero)
364 }
365}
366
367impl TryCoerce<NonZeroIsize> for i32 {
369 type Error = CoerceError;
370
371 #[inline]
372 fn try_coerce(self) -> Result<NonZeroIsize, CoerceError> {
373 NonZeroIsize::new(self as isize).ok_or(CoerceError::Zero)
374 }
375}
376
377impl TryCoerce<NonZeroU32> for i32 {
379 type Error = CoerceError;
380
381 #[inline]
382 fn try_coerce(self) -> Result<NonZeroU32, CoerceError> {
383 let u: u32 = self.try_into().map_err(|_| CoerceError::Overflow)?;
384 NonZeroU32::new(u).ok_or(CoerceError::Zero)
385 }
386}
387
388impl TryCoerce<NonZeroU64> for i32 {
390 type Error = CoerceError;
391
392 #[inline]
393 fn try_coerce(self) -> Result<NonZeroU64, CoerceError> {
394 let u: u64 = self.try_into().map_err(|_| CoerceError::Overflow)?;
395 NonZeroU64::new(u).ok_or(CoerceError::Zero)
396 }
397}
398
399impl TryCoerce<NonZeroUsize> for i32 {
401 type Error = CoerceError;
402
403 #[inline]
404 fn try_coerce(self) -> Result<NonZeroUsize, CoerceError> {
405 let u: usize = self.try_into().map_err(|_| CoerceError::Overflow)?;
406 NonZeroUsize::new(u).ok_or(CoerceError::Zero)
407 }
408}
409
410impl TryCoerce<NonZeroI8> for i32 {
412 type Error = CoerceError;
413
414 #[inline]
415 fn try_coerce(self) -> Result<NonZeroI8, CoerceError> {
416 let n: i8 = self.try_into().map_err(|_| CoerceError::Overflow)?;
417 NonZeroI8::new(n).ok_or(CoerceError::Zero)
418 }
419}
420
421impl TryCoerce<NonZeroI16> for i32 {
423 type Error = CoerceError;
424
425 #[inline]
426 fn try_coerce(self) -> Result<NonZeroI16, CoerceError> {
427 let n: i16 = self.try_into().map_err(|_| CoerceError::Overflow)?;
428 NonZeroI16::new(n).ok_or(CoerceError::Zero)
429 }
430}
431
432impl TryCoerce<NonZeroU8> for i32 {
434 type Error = CoerceError;
435
436 #[inline]
437 fn try_coerce(self) -> Result<NonZeroU8, CoerceError> {
438 let u: u8 = self.try_into().map_err(|_| CoerceError::Overflow)?;
439 NonZeroU8::new(u).ok_or(CoerceError::Zero)
440 }
441}
442
443impl TryCoerce<NonZeroU16> for i32 {
445 type Error = CoerceError;
446
447 #[inline]
448 fn try_coerce(self) -> Result<NonZeroU16, CoerceError> {
449 let u: u16 = self.try_into().map_err(|_| CoerceError::Overflow)?;
450 NonZeroU16::new(u).ok_or(CoerceError::Zero)
451 }
452}
453#[derive(Debug, Clone, Copy, PartialEq, Eq)]
459pub enum LogicalCoerceError {
460 NAValue,
462 InvalidValue(i32),
464}
465
466impl std::fmt::Display for LogicalCoerceError {
467 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
468 match self {
469 LogicalCoerceError::NAValue => write!(f, "NA cannot be converted to bool"),
470 LogicalCoerceError::InvalidValue(v) => write!(f, "invalid logical value: {}", v),
471 }
472 }
473}
474
475impl std::error::Error for LogicalCoerceError {}
476
477impl TryCoerce<bool> for i32 {
478 type Error = LogicalCoerceError;
479
480 #[inline]
481 fn try_coerce(self) -> Result<bool, LogicalCoerceError> {
482 match self {
483 0 => Ok(false),
484 1 => Ok(true),
485 i32::MIN => Err(LogicalCoerceError::NAValue),
487 other => Err(LogicalCoerceError::InvalidValue(other)),
488 }
489 }
490}
491
492impl TryCoerce<bool> for Rboolean {
493 type Error = LogicalCoerceError;
494
495 #[inline]
496 fn try_coerce(self) -> Result<bool, LogicalCoerceError> {
497 (self as i32).try_coerce()
498 }
499}
500
501impl TryCoerce<bool> for crate::ffi::RLogical {
502 type Error = LogicalCoerceError;
503
504 #[inline]
505 fn try_coerce(self) -> Result<bool, LogicalCoerceError> {
506 self.to_i32().try_coerce()
507 }
508}
509macro_rules! impl_try_i32 {
514 ($t:ty) => {
515 impl TryCoerce<i32> for $t {
516 type Error = CoerceError;
517 #[inline]
518 fn try_coerce(self) -> Result<i32, CoerceError> {
519 self.try_into().map_err(|_| CoerceError::Overflow)
520 }
521 }
522 };
523}
524
525impl_try_i32!(u32);
526impl_try_i32!(u64);
527impl_try_i32!(usize);
528impl_try_i32!(i64);
529impl_try_i32!(isize);
530macro_rules! impl_try_u8 {
535 ($t:ty) => {
536 impl TryCoerce<u8> for $t {
537 type Error = CoerceError;
538 #[inline]
539 fn try_coerce(self) -> Result<u8, CoerceError> {
540 self.try_into().map_err(|_| CoerceError::Overflow)
541 }
542 }
543 };
544}
545
546impl_try_u8!(i8);
547impl_try_u8!(i16);
548impl_try_u8!(i32);
549impl_try_u8!(i64);
550impl_try_u8!(u16);
551impl_try_u8!(u32);
552impl_try_u8!(u64);
553impl_try_u8!(usize);
554impl_try_u8!(isize);
555impl Coerce<u16> for u8 {
560 #[inline(always)]
561 fn coerce(self) -> u16 {
562 self.into()
563 }
564}
565
566impl Coerce<i16> for i8 {
567 #[inline(always)]
568 fn coerce(self) -> i16 {
569 self.into()
570 }
571}
572
573impl Coerce<i16> for u8 {
574 #[inline(always)]
575 fn coerce(self) -> i16 {
576 self.into()
577 }
578}
579
580impl Coerce<u32> for u8 {
581 #[inline(always)]
582 fn coerce(self) -> u32 {
583 self.into()
584 }
585}
586
587impl Coerce<u32> for u16 {
588 #[inline(always)]
589 fn coerce(self) -> u32 {
590 self.into()
591 }
592}
593macro_rules! impl_try_u16 {
598 ($t:ty) => {
599 impl TryCoerce<u16> for $t {
600 type Error = CoerceError;
601 #[inline]
602 fn try_coerce(self) -> Result<u16, CoerceError> {
603 self.try_into().map_err(|_| CoerceError::Overflow)
604 }
605 }
606 };
607}
608
609impl_try_u16!(i8);
610impl_try_u16!(i16);
611impl_try_u16!(i32);
612impl_try_u16!(i64);
613impl_try_u16!(u32);
614impl_try_u16!(u64);
615impl_try_u16!(usize);
616impl_try_u16!(isize);
617macro_rules! impl_try_i16 {
622 ($t:ty) => {
623 impl TryCoerce<i16> for $t {
624 type Error = CoerceError;
625 #[inline]
626 fn try_coerce(self) -> Result<i16, CoerceError> {
627 self.try_into().map_err(|_| CoerceError::Overflow)
628 }
629 }
630 };
631}
632
633impl_try_i16!(i32);
634impl_try_i16!(i64);
635impl_try_i16!(u16);
636impl_try_i16!(u32);
637impl_try_i16!(u64);
638impl_try_i16!(usize);
639impl_try_i16!(isize);
640macro_rules! impl_try_i8 {
645 ($t:ty) => {
646 impl TryCoerce<i8> for $t {
647 type Error = CoerceError;
648 #[inline]
649 fn try_coerce(self) -> Result<i8, CoerceError> {
650 self.try_into().map_err(|_| CoerceError::Overflow)
651 }
652 }
653 };
654}
655
656impl_try_i8!(i16);
657impl_try_i8!(i32);
658impl_try_i8!(i64);
659impl_try_i8!(u8);
660impl_try_i8!(u16);
661impl_try_i8!(u32);
662impl_try_i8!(u64);
663impl_try_i8!(usize);
664impl_try_i8!(isize);
665impl TryCoerce<u16> for f64 {
670 type Error = CoerceError;
671
672 #[inline]
673 fn try_coerce(self) -> Result<u16, CoerceError> {
674 if self.is_nan() {
675 return Err(CoerceError::NaN);
676 }
677 if self.is_infinite() {
678 return Err(CoerceError::Overflow);
679 }
680 if self < 0.0 || self > u16::MAX as f64 {
681 return Err(CoerceError::Overflow);
682 }
683 if self.fract() != 0.0 {
684 return Err(CoerceError::PrecisionLoss);
685 }
686 Ok(self as u16)
687 }
688}
689
690impl TryCoerce<i16> for f64 {
691 type Error = CoerceError;
692
693 #[inline]
694 fn try_coerce(self) -> Result<i16, CoerceError> {
695 if self.is_nan() {
696 return Err(CoerceError::NaN);
697 }
698 if self.is_infinite() {
699 return Err(CoerceError::Overflow);
700 }
701 if self < i16::MIN as f64 || self > i16::MAX as f64 {
702 return Err(CoerceError::Overflow);
703 }
704 if self.fract() != 0.0 {
705 return Err(CoerceError::PrecisionLoss);
706 }
707 Ok(self as i16)
708 }
709}
710
711impl TryCoerce<i8> for f64 {
712 type Error = CoerceError;
713
714 #[inline]
715 fn try_coerce(self) -> Result<i8, CoerceError> {
716 if self.is_nan() {
717 return Err(CoerceError::NaN);
718 }
719 if self.is_infinite() {
720 return Err(CoerceError::Overflow);
721 }
722 if self < i8::MIN as f64 || self > i8::MAX as f64 {
723 return Err(CoerceError::Overflow);
724 }
725 if self.fract() != 0.0 {
726 return Err(CoerceError::PrecisionLoss);
727 }
728 Ok(self as i8)
729 }
730}
731impl TryCoerce<i32> for f64 {
736 type Error = CoerceError;
737
738 #[inline]
739 fn try_coerce(self) -> Result<i32, CoerceError> {
740 if self.is_nan() {
741 return Err(CoerceError::NaN);
742 }
743 if self.is_infinite() {
744 return Err(CoerceError::Overflow);
745 }
746 if self < i32::MIN as f64 || self > i32::MAX as f64 {
747 return Err(CoerceError::Overflow);
748 }
749 if self.fract() != 0.0 {
750 return Err(CoerceError::PrecisionLoss);
751 }
752 Ok(self as i32)
753 }
754}
755
756impl TryCoerce<i32> for f32 {
757 type Error = CoerceError;
758
759 #[inline]
760 fn try_coerce(self) -> Result<i32, CoerceError> {
761 f64::from(self).try_coerce()
762 }
763}
764
765impl Coerce<f32> for f64 {
767 #[inline(always)]
768 fn coerce(self) -> f32 {
769 self as f32
770 }
771}
772impl TryCoerce<u8> for f64 {
777 type Error = CoerceError;
778
779 #[inline]
780 fn try_coerce(self) -> Result<u8, CoerceError> {
781 if self.is_nan() {
782 return Err(CoerceError::NaN);
783 }
784 if self.is_infinite() {
785 return Err(CoerceError::Overflow);
786 }
787 if self < 0.0 || self > u8::MAX as f64 {
788 return Err(CoerceError::Overflow);
789 }
790 if self.fract() != 0.0 {
791 return Err(CoerceError::PrecisionLoss);
792 }
793 Ok(self as u8)
794 }
795}
796
797impl TryCoerce<u8> for f32 {
798 type Error = CoerceError;
799
800 #[inline]
801 fn try_coerce(self) -> Result<u8, CoerceError> {
802 f64::from(self).try_coerce()
803 }
804}
805impl TryCoerce<u32> for f64 {
810 type Error = CoerceError;
811
812 #[inline]
813 fn try_coerce(self) -> Result<u32, CoerceError> {
814 if self.is_nan() {
815 return Err(CoerceError::NaN);
816 }
817 if self.is_infinite() {
818 return Err(CoerceError::Overflow);
819 }
820 if self < 0.0 || self > u32::MAX as f64 {
821 return Err(CoerceError::Overflow);
822 }
823 if self.fract() != 0.0 {
824 return Err(CoerceError::PrecisionLoss);
825 }
826 Ok(self as u32)
827 }
828}
829impl TryCoerce<i64> for f64 {
850 type Error = CoerceError;
851
852 #[inline]
853 fn try_coerce(self) -> Result<i64, CoerceError> {
854 if self.is_nan() {
855 return Err(CoerceError::NaN);
856 }
857 if self.is_infinite() {
858 return Err(CoerceError::Overflow);
859 }
860 if self < i64::MIN as f64 || self >= i64::MAX as f64 {
862 return Err(CoerceError::Overflow);
863 }
864 if self.fract() != 0.0 {
865 return Err(CoerceError::PrecisionLoss);
866 }
867 Ok(self as i64)
868 }
869}
870
871impl TryCoerce<u64> for f64 {
872 type Error = CoerceError;
873
874 #[inline]
875 fn try_coerce(self) -> Result<u64, CoerceError> {
876 if self.is_nan() {
877 return Err(CoerceError::NaN);
878 }
879 if self.is_infinite() {
880 return Err(CoerceError::Overflow);
881 }
882 if self < 0.0 || self >= u64::MAX as f64 {
883 return Err(CoerceError::Overflow);
884 }
885 if self.fract() != 0.0 {
886 return Err(CoerceError::PrecisionLoss);
887 }
888 Ok(self as u64)
889 }
890}
891
892impl TryCoerce<isize> for f64 {
893 type Error = CoerceError;
894
895 #[inline]
896 fn try_coerce(self) -> Result<isize, CoerceError> {
897 if self.is_nan() {
898 return Err(CoerceError::NaN);
899 }
900 if self.is_infinite() {
901 return Err(CoerceError::Overflow);
902 }
903 if self < isize::MIN as f64 || self >= isize::MAX as f64 {
905 return Err(CoerceError::Overflow);
906 }
907 if self.fract() != 0.0 {
908 return Err(CoerceError::PrecisionLoss);
909 }
910 Ok(self as isize)
911 }
912}
913
914impl TryCoerce<usize> for f64 {
915 type Error = CoerceError;
916
917 #[inline]
918 fn try_coerce(self) -> Result<usize, CoerceError> {
919 if self.is_nan() {
920 return Err(CoerceError::NaN);
921 }
922 if self.is_infinite() {
923 return Err(CoerceError::Overflow);
924 }
925 if self < 0.0 || self >= usize::MAX as f64 {
927 return Err(CoerceError::Overflow);
928 }
929 if self.fract() != 0.0 {
930 return Err(CoerceError::PrecisionLoss);
931 }
932 Ok(self as usize)
933 }
934}
935impl TryCoerce<f64> for i64 {
956 type Error = CoerceError;
957
958 #[inline]
959 fn try_coerce(self) -> Result<f64, CoerceError> {
960 const MAX_SAFE: i64 = 1 << 53;
961 const MIN_SAFE: i64 = -(1 << 53);
962 if !(MIN_SAFE..=MAX_SAFE).contains(&self) {
963 return Err(CoerceError::PrecisionLoss);
964 }
965 Ok(self as f64)
966 }
967}
968
969impl TryCoerce<f64> for u64 {
973 type Error = CoerceError;
974
975 #[inline]
976 fn try_coerce(self) -> Result<f64, CoerceError> {
977 const MAX_SAFE: u64 = 1 << 53;
978 if self > MAX_SAFE {
979 return Err(CoerceError::PrecisionLoss);
980 }
981 Ok(self as f64)
982 }
983}
984
985impl TryCoerce<f64> for isize {
986 type Error = CoerceError;
987 #[inline]
988 fn try_coerce(self) -> Result<f64, CoerceError> {
989 (self as i64).try_coerce()
990 }
991}
992
993impl TryCoerce<f64> for usize {
994 type Error = CoerceError;
995 #[inline]
996 fn try_coerce(self) -> Result<f64, CoerceError> {
997 (self as u64).try_coerce()
998 }
999}
1000use std::marker::PhantomData;
1005
1006#[repr(transparent)]
1022#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1023pub struct Coerced<T, R> {
1024 value: T,
1025 _marker: PhantomData<R>,
1026}
1027
1028impl<T, R> Coerced<T, R> {
1029 #[inline]
1031 pub const fn new(value: T) -> Self {
1032 Self {
1033 value,
1034 _marker: PhantomData,
1035 }
1036 }
1037
1038 #[inline]
1040 pub fn into_inner(self) -> T {
1041 self.value
1042 }
1043
1044 #[inline]
1046 pub const fn as_inner(&self) -> &T {
1047 &self.value
1048 }
1049
1050 #[inline]
1052 pub fn as_inner_mut(&mut self) -> &mut T {
1053 &mut self.value
1054 }
1055}
1056
1057impl<T, R> std::ops::Deref for Coerced<T, R> {
1058 type Target = T;
1059
1060 #[inline]
1061 fn deref(&self) -> &Self::Target {
1062 &self.value
1063 }
1064}
1065
1066impl<T, R> std::ops::DerefMut for Coerced<T, R> {
1067 #[inline]
1068 fn deref_mut(&mut self) -> &mut Self::Target {
1069 &mut self.value
1070 }
1071}
1072impl<T: Copy + Coerce<R>, R> Coerce<Vec<R>> for &[T] {
1078 #[inline]
1079 fn coerce(self) -> Vec<R> {
1080 self.iter().copied().map(Coerce::coerce).collect()
1081 }
1082}
1083
1084impl<T: Coerce<R>, R> Coerce<Vec<R>> for Vec<T> {
1086 #[inline]
1087 fn coerce(self) -> Vec<R> {
1088 self.into_iter().map(Coerce::coerce).collect()
1089 }
1090}
1091
1092impl<T: Coerce<R>, R> Coerce<Box<[R]>> for Box<[T]> {
1094 #[inline]
1095 fn coerce(self) -> Box<[R]> {
1096 Vec::from(self).into_iter().map(Coerce::coerce).collect()
1097 }
1098}
1099
1100impl<T: Coerce<R>, R> Coerce<std::collections::VecDeque<R>> for std::collections::VecDeque<T> {
1102 fn coerce(self) -> std::collections::VecDeque<R> {
1103 self.into_iter().map(Coerce::coerce).collect()
1104 }
1105}
1106
1107#[cfg(feature = "tinyvec")]
1116impl<T, R, const N: usize> Coerce<tinyvec::TinyVec<[R; N]>> for tinyvec::TinyVec<[T; N]>
1120where
1121 T: Coerce<R>,
1122 [T; N]: tinyvec::Array<Item = T>,
1123 [R; N]: tinyvec::Array<Item = R>,
1124{
1125 fn coerce(self) -> tinyvec::TinyVec<[R; N]> {
1126 self.into_iter().map(Coerce::coerce).collect()
1127 }
1128}
1129
1130#[cfg(feature = "tinyvec")]
1131impl<T, R, const N: usize> Coerce<tinyvec::ArrayVec<[R; N]>> for tinyvec::ArrayVec<[T; N]>
1135where
1136 T: Coerce<R>,
1137 [T; N]: tinyvec::Array<Item = T>,
1138 [R; N]: tinyvec::Array<Item = R>,
1139{
1140 fn coerce(self) -> tinyvec::ArrayVec<[R; N]> {
1141 self.into_iter().map(Coerce::coerce).collect()
1142 }
1143}
1144macro_rules! impl_tuple_coerce {
1150 (($($T:ident),+), ($($R:ident),+), ($($idx:tt),+)) => {
1151 impl<$($T,)+ $($R,)+> Coerce<($($R,)+)> for ($($T,)+)
1152 where
1153 $($T: Coerce<$R>,)+
1154 {
1155 #[inline]
1156 fn coerce(self) -> ($($R,)+) {
1157 ($(Coerce::<$R>::coerce(self.$idx),)+)
1158 }
1159 }
1160 };
1161}
1162
1163impl_tuple_coerce!((A, B), (RA, RB), (0, 1));
1165impl_tuple_coerce!((A, B, C), (RA, RB, RC), (0, 1, 2));
1166impl_tuple_coerce!((A, B, C, D), (RA, RB, RC, RD), (0, 1, 2, 3));
1167impl_tuple_coerce!((A, B, C, D, E), (RA, RB, RC, RD, RE), (0, 1, 2, 3, 4));
1168impl_tuple_coerce!(
1169 (A, B, C, D, E, F),
1170 (RA, RB, RC, RD, RE, RF),
1171 (0, 1, 2, 3, 4, 5)
1172);
1173impl_tuple_coerce!(
1174 (A, B, C, D, E, F, G),
1175 (RA, RB, RC, RD, RE, RF, RG),
1176 (0, 1, 2, 3, 4, 5, 6)
1177);
1178impl_tuple_coerce!(
1179 (A, B, C, D, E, F, G, H),
1180 (RA, RB, RC, RD, RE, RF, RG, RH),
1181 (0, 1, 2, 3, 4, 5, 6, 7)
1182);
1183#[cfg(test)]
1188mod tests;
1189