1#[cfg(not(no_zerocopy_core_error_1_81_0))]
119use core::error::Error;
120use core::{
121 convert::Infallible,
122 fmt::{self, Debug, Write},
123 ops::Deref,
124};
125#[cfg(all(no_zerocopy_core_error_1_81_0, any(feature = "std", test)))]
126use std::error::Error;
127
128use crate::{util::SendSyncPhantomData, KnownLayout, TryFromBytes, Unaligned};
129#[cfg(doc)]
130use crate::{FromBytes, Ref};
131
132#[derive(PartialEq, Eq, Clone)]
153pub enum ConvertError<A, S, V> {
154 Alignment(A),
156 Size(S),
158 Validity(V),
160}
161
162impl<Src, Dst: ?Sized + Unaligned, S, V> From<ConvertError<AlignmentError<Src, Dst>, S, V>>
163 for ConvertError<Infallible, S, V>
164{
165 #[inline]
198 fn from(err: ConvertError<AlignmentError<Src, Dst>, S, V>) -> ConvertError<Infallible, S, V> {
199 match err {
200 ConvertError::Alignment(e) => {
201 #[allow(unreachable_code)]
202 return ConvertError::Alignment(Infallible::from(e));
203 }
204 ConvertError::Size(e) => ConvertError::Size(e),
205 ConvertError::Validity(e) => ConvertError::Validity(e),
206 }
207 }
208}
209
210impl<A: fmt::Debug, S: fmt::Debug, V: fmt::Debug> fmt::Debug for ConvertError<A, S, V> {
211 #[inline]
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 match self {
214 Self::Alignment(e) => f.debug_tuple("Alignment").field(e).finish(),
215 Self::Size(e) => f.debug_tuple("Size").field(e).finish(),
216 Self::Validity(e) => f.debug_tuple("Validity").field(e).finish(),
217 }
218 }
219}
220
221impl<A: fmt::Display, S: fmt::Display, V: fmt::Display> fmt::Display for ConvertError<A, S, V> {
227 #[inline]
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 match self {
230 Self::Alignment(e) => e.fmt(f),
231 Self::Size(e) => e.fmt(f),
232 Self::Validity(e) => e.fmt(f),
233 }
234 }
235}
236
237#[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))]
238#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))]
239impl<A, S, V> Error for ConvertError<A, S, V>
240where
241 A: fmt::Display + fmt::Debug,
242 S: fmt::Display + fmt::Debug,
243 V: fmt::Display + fmt::Debug,
244{
245}
246
247pub struct AlignmentError<Src, Dst: ?Sized> {
249 src: Src,
251 _dst: SendSyncPhantomData<Dst>,
256}
257
258impl<Src, Dst: ?Sized> AlignmentError<Src, Dst> {
259 pub(crate) unsafe fn new_unchecked(src: Src) -> Self {
264 Self { src, _dst: SendSyncPhantomData::default() }
267 }
268
269 #[inline]
271 pub fn into_src(self) -> Src {
272 self.src
273 }
274
275 pub(crate) fn with_src<NewSrc>(self, new_src: NewSrc) -> AlignmentError<NewSrc, Dst> {
276 AlignmentError { src: new_src, _dst: SendSyncPhantomData::default() }
280 }
281
282 #[inline]
303 pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> AlignmentError<NewSrc, Dst> {
304 AlignmentError { src: f(self.src), _dst: SendSyncPhantomData::default() }
305 }
306
307 pub(crate) fn into<S, V>(self) -> ConvertError<Self, S, V> {
308 ConvertError::Alignment(self)
309 }
310
311 fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
315 where
316 Src: Deref,
317 Dst: KnownLayout,
318 {
319 #[allow(clippy::as_conversions)]
320 let addr = self.src.deref() as *const _ as *const ();
321 let addr_align = 2usize.pow((crate::util::AsAddress::addr(addr)).trailing_zeros());
322
323 f.write_str("\n\nSource type: ")?;
324 f.write_str(core::any::type_name::<Src>())?;
325
326 f.write_str("\nSource address: ")?;
327 addr.fmt(f)?;
328 f.write_str(" (a multiple of ")?;
329 addr_align.fmt(f)?;
330 f.write_str(")")?;
331
332 f.write_str("\nDestination type: ")?;
333 f.write_str(core::any::type_name::<Dst>())?;
334
335 f.write_str("\nDestination alignment: ")?;
336 <Dst as KnownLayout>::LAYOUT.align.get().fmt(f)?;
337
338 Ok(())
339 }
340}
341
342impl<Src: Clone, Dst: ?Sized> Clone for AlignmentError<Src, Dst> {
343 #[inline]
344 fn clone(&self) -> Self {
345 Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() }
346 }
347}
348
349impl<Src: PartialEq, Dst: ?Sized> PartialEq for AlignmentError<Src, Dst> {
350 #[inline]
351 fn eq(&self, other: &Self) -> bool {
352 self.src == other.src
353 }
354}
355
356impl<Src: Eq, Dst: ?Sized> Eq for AlignmentError<Src, Dst> {}
357
358impl<Src, Dst: ?Sized + Unaligned> From<AlignmentError<Src, Dst>> for Infallible {
359 #[inline(always)]
360 fn from(_: AlignmentError<Src, Dst>) -> Infallible {
361 unsafe { core::hint::unreachable_unchecked() }
366 }
367}
368
369#[cfg(test)]
370impl<Src, Dst> AlignmentError<Src, Dst> {
371 fn new_checked(src: Src) -> AlignmentError<Src, Dst> {
374 assert_ne!(core::mem::align_of::<Dst>(), 1);
375 unsafe { AlignmentError::new_unchecked(src) }
378 }
379}
380
381impl<Src, Dst: ?Sized> fmt::Debug for AlignmentError<Src, Dst> {
382 #[inline]
383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384 f.debug_struct("AlignmentError").finish()
385 }
386}
387
388impl<Src, Dst: ?Sized> fmt::Display for AlignmentError<Src, Dst>
394where
395 Src: Deref,
396 Dst: KnownLayout,
397{
398 #[inline]
399 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400 f.write_str("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.")?;
401
402 if cfg!(debug_assertions) {
403 self.display_verbose_extras(f)
404 } else {
405 Ok(())
406 }
407 }
408}
409
410#[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))]
411#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))]
412impl<Src, Dst: ?Sized> Error for AlignmentError<Src, Dst>
413where
414 Src: Deref,
415 Dst: KnownLayout,
416{
417}
418
419impl<Src, Dst: ?Sized, S, V> From<AlignmentError<Src, Dst>>
420 for ConvertError<AlignmentError<Src, Dst>, S, V>
421{
422 #[inline(always)]
423 fn from(err: AlignmentError<Src, Dst>) -> Self {
424 Self::Alignment(err)
425 }
426}
427
428pub struct SizeError<Src, Dst: ?Sized> {
430 src: Src,
432 _dst: SendSyncPhantomData<Dst>,
434}
435
436impl<Src, Dst: ?Sized> SizeError<Src, Dst> {
437 pub(crate) fn new(src: Src) -> Self {
438 Self { src, _dst: SendSyncPhantomData::default() }
439 }
440
441 #[inline]
443 pub fn into_src(self) -> Src {
444 self.src
445 }
446
447 pub(crate) fn with_src<NewSrc>(self, new_src: NewSrc) -> SizeError<NewSrc, Dst> {
449 SizeError { src: new_src, _dst: SendSyncPhantomData::default() }
450 }
451
452 #[inline]
474 pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> SizeError<NewSrc, Dst> {
475 SizeError { src: f(self.src), _dst: SendSyncPhantomData::default() }
476 }
477
478 pub(crate) fn with_dst<NewDst: ?Sized>(self) -> SizeError<Src, NewDst> {
480 SizeError { src: self.src, _dst: SendSyncPhantomData::default() }
481 }
482
483 pub(crate) fn into<A, V>(self) -> ConvertError<A, Self, V> {
485 ConvertError::Size(self)
486 }
487
488 fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
492 where
493 Src: Deref,
494 Dst: KnownLayout,
495 {
496 f.write_str("\nSource type: ")?;
498 f.write_str(core::any::type_name::<Src>())?;
499
500 let src_size = core::mem::size_of_val(&*self.src);
502 f.write_str("\nSource size: ")?;
503 src_size.fmt(f)?;
504 f.write_str(" byte")?;
505 if src_size != 1 {
506 f.write_char('s')?;
507 }
508
509 if let crate::SizeInfo::Sized { size } = Dst::LAYOUT.size_info {
511 f.write_str("\nDestination size: ")?;
512 size.fmt(f)?;
513 f.write_str(" byte")?;
514 if size != 1 {
515 f.write_char('s')?;
516 }
517 }
518
519 f.write_str("\nDestination type: ")?;
521 f.write_str(core::any::type_name::<Dst>())?;
522
523 Ok(())
524 }
525}
526
527impl<Src: Clone, Dst: ?Sized> Clone for SizeError<Src, Dst> {
528 #[inline]
529 fn clone(&self) -> Self {
530 Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() }
531 }
532}
533
534impl<Src: PartialEq, Dst: ?Sized> PartialEq for SizeError<Src, Dst> {
535 #[inline]
536 fn eq(&self, other: &Self) -> bool {
537 self.src == other.src
538 }
539}
540
541impl<Src: Eq, Dst: ?Sized> Eq for SizeError<Src, Dst> {}
542
543impl<Src, Dst: ?Sized> fmt::Debug for SizeError<Src, Dst> {
544 #[inline]
545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546 f.debug_struct("SizeError").finish()
547 }
548}
549
550impl<Src, Dst: ?Sized> fmt::Display for SizeError<Src, Dst>
556where
557 Src: Deref,
558 Dst: KnownLayout,
559{
560 #[inline]
561 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
562 f.write_str("The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.")?;
563 if cfg!(debug_assertions) {
564 f.write_str("\n")?;
565 self.display_verbose_extras(f)?;
566 }
567 Ok(())
568 }
569}
570
571#[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))]
572#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))]
573impl<Src, Dst: ?Sized> Error for SizeError<Src, Dst>
574where
575 Src: Deref,
576 Dst: KnownLayout,
577{
578}
579
580impl<Src, Dst: ?Sized, A, V> From<SizeError<Src, Dst>> for ConvertError<A, SizeError<Src, Dst>, V> {
581 #[inline(always)]
582 fn from(err: SizeError<Src, Dst>) -> Self {
583 Self::Size(err)
584 }
585}
586
587pub struct ValidityError<Src, Dst: ?Sized + TryFromBytes> {
589 pub(crate) src: Src,
591 _dst: SendSyncPhantomData<Dst>,
593}
594
595impl<Src, Dst: ?Sized + TryFromBytes> ValidityError<Src, Dst> {
596 pub(crate) fn new(src: Src) -> Self {
597 Self { src, _dst: SendSyncPhantomData::default() }
598 }
599
600 #[inline]
602 pub fn into_src(self) -> Src {
603 self.src
604 }
605
606 #[inline]
627 pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> ValidityError<NewSrc, Dst> {
628 ValidityError { src: f(self.src), _dst: SendSyncPhantomData::default() }
629 }
630
631 pub(crate) fn into<A, S>(self) -> ConvertError<A, S, Self> {
633 ConvertError::Validity(self)
634 }
635
636 fn display_verbose_extras(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
640 where
641 Dst: KnownLayout,
642 {
643 f.write_str("Destination type: ")?;
644 f.write_str(core::any::type_name::<Dst>())?;
645 Ok(())
646 }
647}
648
649impl<Src: Clone, Dst: ?Sized + TryFromBytes> Clone for ValidityError<Src, Dst> {
650 #[inline]
651 fn clone(&self) -> Self {
652 Self { src: self.src.clone(), _dst: SendSyncPhantomData::default() }
653 }
654}
655
656unsafe impl<Src, NewSrc, Dst> crate::pointer::TryWithError<NewSrc>
659 for crate::ValidityError<Src, Dst>
660where
661 Dst: TryFromBytes + ?Sized,
662{
663 type Inner = Src;
664 type Mapped = crate::ValidityError<NewSrc, Dst>;
665 #[inline]
666 fn map<F: FnOnce(Src) -> NewSrc>(self, f: F) -> Self::Mapped {
667 self.map_src(f)
668 }
669}
670
671impl<Src: PartialEq, Dst: ?Sized + TryFromBytes> PartialEq for ValidityError<Src, Dst> {
672 #[inline]
673 fn eq(&self, other: &Self) -> bool {
674 self.src == other.src
675 }
676}
677
678impl<Src: Eq, Dst: ?Sized + TryFromBytes> Eq for ValidityError<Src, Dst> {}
679
680impl<Src, Dst: ?Sized + TryFromBytes> fmt::Debug for ValidityError<Src, Dst> {
681 #[inline]
682 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
683 f.debug_struct("ValidityError").finish()
684 }
685}
686
687impl<Src, Dst: ?Sized> fmt::Display for ValidityError<Src, Dst>
693where
694 Dst: KnownLayout + TryFromBytes,
695{
696 #[inline]
697 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
698 f.write_str("The conversion failed because the source bytes are not a valid value of the destination type.")?;
699 if cfg!(debug_assertions) {
700 f.write_str("\n\n")?;
701 self.display_verbose_extras(f)?;
702 }
703 Ok(())
704 }
705}
706
707#[cfg(any(not(no_zerocopy_core_error_1_81_0), feature = "std", test))]
708#[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.81.0", feature = "std"))))]
709impl<Src, Dst: ?Sized> Error for ValidityError<Src, Dst> where Dst: KnownLayout + TryFromBytes {}
710
711impl<Src, Dst: ?Sized + TryFromBytes, A, S> From<ValidityError<Src, Dst>>
712 for ConvertError<A, S, ValidityError<Src, Dst>>
713{
714 #[inline(always)]
715 fn from(err: ValidityError<Src, Dst>) -> Self {
716 Self::Validity(err)
717 }
718}
719
720#[allow(type_alias_bounds)]
727pub type CastError<Src, Dst: ?Sized> =
728 ConvertError<AlignmentError<Src, Dst>, SizeError<Src, Dst>, Infallible>;
729
730impl<Src, Dst: ?Sized> CastError<Src, Dst> {
731 #[inline]
733 pub fn into_src(self) -> Src {
734 match self {
735 Self::Alignment(e) => e.src,
736 Self::Size(e) => e.src,
737 Self::Validity(i) => match i {},
738 }
739 }
740
741 pub(crate) fn with_src<NewSrc>(self, new_src: NewSrc) -> CastError<NewSrc, Dst> {
743 match self {
744 Self::Alignment(e) => CastError::Alignment(e.with_src(new_src)),
745 Self::Size(e) => CastError::Size(e.with_src(new_src)),
746 Self::Validity(i) => match i {},
747 }
748 }
749
750 #[inline]
772 pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> CastError<NewSrc, Dst> {
773 match self {
774 Self::Alignment(e) => CastError::Alignment(e.map_src(f)),
775 Self::Size(e) => CastError::Size(e.map_src(f)),
776 Self::Validity(i) => match i {},
777 }
778 }
779
780 pub(crate) fn into(self) -> TryCastError<Src, Dst>
782 where
783 Dst: TryFromBytes,
784 {
785 match self {
786 Self::Alignment(e) => TryCastError::Alignment(e),
787 Self::Size(e) => TryCastError::Size(e),
788 Self::Validity(i) => match i {},
789 }
790 }
791}
792
793unsafe impl<Src, NewSrc, Dst> crate::pointer::TryWithError<NewSrc> for crate::CastError<Src, Dst>
798where
799 Dst: ?Sized,
800{
801 type Inner = Src;
802 type Mapped = crate::CastError<NewSrc, Dst>;
803
804 #[inline]
805 fn map<F: FnOnce(Src) -> NewSrc>(self, f: F) -> Self::Mapped {
806 self.map_src(f)
807 }
808}
809
810impl<Src, Dst: ?Sized + Unaligned> From<CastError<Src, Dst>> for SizeError<Src, Dst> {
811 #[inline(always)]
851 fn from(err: CastError<Src, Dst>) -> SizeError<Src, Dst> {
852 match err {
853 #[allow(unreachable_code)]
854 CastError::Alignment(e) => match Infallible::from(e) {},
855 CastError::Size(e) => e,
856 CastError::Validity(i) => match i {},
857 }
858 }
859}
860
861#[allow(type_alias_bounds)]
869pub type TryCastError<Src, Dst: ?Sized + TryFromBytes> =
870 ConvertError<AlignmentError<Src, Dst>, SizeError<Src, Dst>, ValidityError<Src, Dst>>;
871
872impl<Src, Dst: ?Sized + TryFromBytes> TryCastError<Src, Dst> {
876 #[inline]
878 pub fn into_src(self) -> Src {
879 match self {
880 Self::Alignment(e) => e.src,
881 Self::Size(e) => e.src,
882 Self::Validity(e) => e.src,
883 }
884 }
885
886 #[inline]
910 pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> TryCastError<NewSrc, Dst> {
911 match self {
912 Self::Alignment(e) => TryCastError::Alignment(e.map_src(f)),
913 Self::Size(e) => TryCastError::Size(e.map_src(f)),
914 Self::Validity(e) => TryCastError::Validity(e.map_src(f)),
915 }
916 }
917}
918
919impl<Src, Dst: ?Sized + TryFromBytes> From<CastError<Src, Dst>> for TryCastError<Src, Dst> {
920 #[inline]
921 fn from(value: CastError<Src, Dst>) -> Self {
922 match value {
923 CastError::Alignment(e) => Self::Alignment(e),
924 CastError::Size(e) => Self::Size(e),
925 CastError::Validity(i) => match i {},
926 }
927 }
928}
929
930#[allow(type_alias_bounds)]
938pub type TryReadError<Src, Dst: ?Sized + TryFromBytes> =
939 ConvertError<Infallible, SizeError<Src, Dst>, ValidityError<Src, Dst>>;
940
941impl<Src, Dst: ?Sized + TryFromBytes> TryReadError<Src, Dst> {
942 #[inline]
944 pub fn into_src(self) -> Src {
945 match self {
946 Self::Alignment(i) => match i {},
947 Self::Size(e) => e.src,
948 Self::Validity(e) => e.src,
949 }
950 }
951
952 #[inline]
976 pub fn map_src<NewSrc>(self, f: impl FnOnce(Src) -> NewSrc) -> TryReadError<NewSrc, Dst> {
977 match self {
978 Self::Alignment(i) => match i {},
979 Self::Size(e) => TryReadError::Size(e.map_src(f)),
980 Self::Validity(e) => TryReadError::Validity(e.map_src(f)),
981 }
982 }
983}
984
985#[allow(type_alias_bounds)]
1019pub type AlignedTryCastError<Src, Dst: ?Sized + TryFromBytes> =
1020 ConvertError<Infallible, SizeError<Src, Dst>, ValidityError<Src, Dst>>;
1021
1022#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1034pub struct AllocError;
1035
1036#[cfg(test)]
1037mod tests {
1038 use core::convert::Infallible;
1039
1040 use super::*;
1041
1042 #[test]
1043 fn test_send_sync() {
1044 #[allow(dead_code)]
1048 fn is_send_sync<T: Send + Sync>(_t: T) {}
1049
1050 #[allow(dead_code)]
1051 fn alignment_err_is_send_sync<Src: Send + Sync, Dst>(err: AlignmentError<Src, Dst>) {
1052 is_send_sync(err)
1053 }
1054
1055 #[allow(dead_code)]
1056 fn size_err_is_send_sync<Src: Send + Sync, Dst>(err: SizeError<Src, Dst>) {
1057 is_send_sync(err)
1058 }
1059
1060 #[allow(dead_code)]
1061 fn validity_err_is_send_sync<Src: Send + Sync, Dst: TryFromBytes>(
1062 err: ValidityError<Src, Dst>,
1063 ) {
1064 is_send_sync(err)
1065 }
1066
1067 #[allow(dead_code)]
1068 fn convert_error_is_send_sync<Src: Send + Sync, Dst: TryFromBytes>(
1069 err: ConvertError<
1070 AlignmentError<Src, Dst>,
1071 SizeError<Src, Dst>,
1072 ValidityError<Src, Dst>,
1073 >,
1074 ) {
1075 is_send_sync(err)
1076 }
1077 }
1078
1079 #[test]
1080 fn test_eq_partial_eq_clone() {
1081 #[allow(dead_code)]
1086 fn is_eq_partial_eq_clone<T: Eq + PartialEq + Clone>(_t: T) {}
1087
1088 #[allow(dead_code)]
1089 fn alignment_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst>(
1090 err: AlignmentError<Src, Dst>,
1091 ) {
1092 is_eq_partial_eq_clone(err)
1093 }
1094
1095 #[allow(dead_code)]
1096 fn size_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst>(
1097 err: SizeError<Src, Dst>,
1098 ) {
1099 is_eq_partial_eq_clone(err)
1100 }
1101
1102 #[allow(dead_code)]
1103 fn validity_err_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst: TryFromBytes>(
1104 err: ValidityError<Src, Dst>,
1105 ) {
1106 is_eq_partial_eq_clone(err)
1107 }
1108
1109 #[allow(dead_code)]
1110 fn convert_error_is_eq_partial_eq_clone<Src: Eq + PartialEq + Clone, Dst: TryFromBytes>(
1111 err: ConvertError<
1112 AlignmentError<Src, Dst>,
1113 SizeError<Src, Dst>,
1114 ValidityError<Src, Dst>,
1115 >,
1116 ) {
1117 is_eq_partial_eq_clone(err)
1118 }
1119 }
1120
1121 #[test]
1122 fn alignment_display() {
1123 #[repr(C, align(128))]
1124 struct Aligned {
1125 bytes: [u8; 128],
1126 }
1127
1128 impl_known_layout!(elain::Align::<8>);
1129
1130 let aligned = Aligned { bytes: [0; 128] };
1131
1132 let bytes = &aligned.bytes[1..];
1133 let addr = crate::util::AsAddress::addr(bytes);
1134 assert_eq!(
1135 AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(),
1136 format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\
1137 \nSource type: &[u8]\
1138 \nSource address: 0x{:x} (a multiple of 1)\
1139 \nDestination type: elain::Align<8>\
1140 \nDestination alignment: 8", addr)
1141 );
1142
1143 let bytes = &aligned.bytes[2..];
1144 let addr = crate::util::AsAddress::addr(bytes);
1145 assert_eq!(
1146 AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(),
1147 format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\
1148 \nSource type: &[u8]\
1149 \nSource address: 0x{:x} (a multiple of 2)\
1150 \nDestination type: elain::Align<8>\
1151 \nDestination alignment: 8", addr)
1152 );
1153
1154 let bytes = &aligned.bytes[3..];
1155 let addr = crate::util::AsAddress::addr(bytes);
1156 assert_eq!(
1157 AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(),
1158 format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\
1159 \nSource type: &[u8]\
1160 \nSource address: 0x{:x} (a multiple of 1)\
1161 \nDestination type: elain::Align<8>\
1162 \nDestination alignment: 8", addr)
1163 );
1164
1165 let bytes = &aligned.bytes[4..];
1166 let addr = crate::util::AsAddress::addr(bytes);
1167 assert_eq!(
1168 AlignmentError::<_, elain::Align::<8>>::new_checked(bytes).to_string(),
1169 format!("The conversion failed because the address of the source is not a multiple of the alignment of the destination type.\n\
1170 \nSource type: &[u8]\
1171 \nSource address: 0x{:x} (a multiple of 4)\
1172 \nDestination type: elain::Align<8>\
1173 \nDestination alignment: 8", addr)
1174 );
1175 }
1176
1177 #[test]
1178 fn size_display() {
1179 assert_eq!(
1180 SizeError::<_, [u8]>::new(&[0u8; 2][..]).to_string(),
1181 "The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.\n\
1182 \nSource type: &[u8]\
1183 \nSource size: 2 bytes\
1184 \nDestination type: [u8]"
1185 );
1186
1187 assert_eq!(
1188 SizeError::<_, [u8; 2]>::new(&[0u8; 1][..]).to_string(),
1189 "The conversion failed because the source was incorrectly sized to complete the conversion into the destination type.\n\
1190 \nSource type: &[u8]\
1191 \nSource size: 1 byte\
1192 \nDestination size: 2 bytes\
1193 \nDestination type: [u8; 2]"
1194 );
1195 }
1196
1197 #[test]
1198 fn validity_display() {
1199 assert_eq!(
1200 ValidityError::<_, bool>::new(&[2u8; 1][..]).to_string(),
1201 "The conversion failed because the source bytes are not a valid value of the destination type.\n\
1202 \n\
1203 Destination type: bool"
1204 );
1205 }
1206
1207 #[test]
1208 fn test_convert_error_debug() {
1209 let err: ConvertError<
1210 AlignmentError<&[u8], u16>,
1211 SizeError<&[u8], u16>,
1212 ValidityError<&[u8], bool>,
1213 > = ConvertError::Alignment(AlignmentError::new_checked(&[0u8]));
1214 assert_eq!(format!("{:?}", err), "Alignment(AlignmentError)");
1215
1216 let err: ConvertError<
1217 AlignmentError<&[u8], u16>,
1218 SizeError<&[u8], u16>,
1219 ValidityError<&[u8], bool>,
1220 > = ConvertError::Size(SizeError::new(&[0u8]));
1221 assert_eq!(format!("{:?}", err), "Size(SizeError)");
1222
1223 let err: ConvertError<
1224 AlignmentError<&[u8], u16>,
1225 SizeError<&[u8], u16>,
1226 ValidityError<&[u8], bool>,
1227 > = ConvertError::Validity(ValidityError::new(&[0u8]));
1228 assert_eq!(format!("{:?}", err), "Validity(ValidityError)");
1229 }
1230
1231 #[test]
1232 fn test_convert_error_from_unaligned() {
1233 let err: ConvertError<
1235 AlignmentError<&[u8], u8>,
1236 SizeError<&[u8], u8>,
1237 ValidityError<&[u8], bool>,
1238 > = ConvertError::Size(SizeError::new(&[0u8]));
1239 let converted: ConvertError<Infallible, SizeError<&[u8], u8>, ValidityError<&[u8], bool>> =
1240 ConvertError::from(err);
1241 match converted {
1242 ConvertError::Size(_) => {}
1243 _ => panic!("Expected Size error"),
1244 }
1245 }
1246
1247 #[test]
1248 fn test_alignment_error_display_debug() {
1249 let err: AlignmentError<&[u8], u16> = AlignmentError::new_checked(&[0u8]);
1250 assert!(format!("{:?}", err).contains("AlignmentError"));
1251 assert!(format!("{}", err).contains("address of the source is not a multiple"));
1252 }
1253
1254 #[test]
1255 fn test_size_error_display_debug() {
1256 let err: SizeError<&[u8], u16> = SizeError::new(&[0u8]);
1257 assert!(format!("{:?}", err).contains("SizeError"));
1258 assert!(format!("{}", err).contains("source was incorrectly sized"));
1259 }
1260
1261 #[test]
1262 fn test_validity_error_display_debug() {
1263 let err: ValidityError<&[u8], bool> = ValidityError::new(&[0u8]);
1264 assert!(format!("{:?}", err).contains("ValidityError"));
1265 assert!(format!("{}", err).contains("source bytes are not a valid value"));
1266 }
1267
1268 #[test]
1269 fn test_convert_error_display_debug_more() {
1270 let err: ConvertError<
1271 AlignmentError<&[u8], u16>,
1272 SizeError<&[u8], u16>,
1273 ValidityError<&[u8], bool>,
1274 > = ConvertError::Alignment(AlignmentError::new_checked(&[0u8]));
1275 assert!(format!("{}", err).contains("address of the source is not a multiple"));
1276
1277 let err: ConvertError<
1278 AlignmentError<&[u8], u16>,
1279 SizeError<&[u8], u16>,
1280 ValidityError<&[u8], bool>,
1281 > = ConvertError::Size(SizeError::new(&[0u8]));
1282 assert!(format!("{}", err).contains("source was incorrectly sized"));
1283
1284 let err: ConvertError<
1285 AlignmentError<&[u8], u16>,
1286 SizeError<&[u8], u16>,
1287 ValidityError<&[u8], bool>,
1288 > = ConvertError::Validity(ValidityError::new(&[0u8]));
1289 assert!(format!("{}", err).contains("source bytes are not a valid value"));
1290 }
1291
1292 #[test]
1293 fn test_alignment_error_methods() {
1294 let err: AlignmentError<&[u8], u16> = AlignmentError::new_checked(&[0u8]);
1295
1296 let src = err.clone().into_src();
1298 assert_eq!(src, &[0u8]);
1299
1300 let converted: ConvertError<
1302 AlignmentError<&[u8], u16>,
1303 SizeError<&[u8], u16>,
1304 ValidityError<&[u8], bool>,
1305 > = err.clone().into();
1306 match converted {
1307 ConvertError::Alignment(_) => {}
1308 _ => panic!("Expected Alignment error"),
1309 }
1310
1311 let cloned = err.clone();
1313 assert_eq!(err, cloned);
1314
1315 assert_eq!(err, cloned);
1317 let err2: AlignmentError<&[u8], u16> = AlignmentError::new_checked(&[1u8]);
1318 assert_ne!(err, err2);
1319 }
1320
1321 #[test]
1322 fn test_convert_error_from_unaligned_variants() {
1323 let err: ConvertError<
1325 AlignmentError<&[u8], u8>,
1326 SizeError<&[u8], u8>,
1327 ValidityError<&[u8], bool>,
1328 > = ConvertError::Validity(ValidityError::new(&[0u8]));
1329 let converted: ConvertError<Infallible, SizeError<&[u8], u8>, ValidityError<&[u8], bool>> =
1330 ConvertError::from(err);
1331 match converted {
1332 ConvertError::Validity(_) => {}
1333 _ => panic!("Expected Validity error"),
1334 }
1335
1336 let err: ConvertError<
1337 AlignmentError<&[u8], u8>,
1338 SizeError<&[u8], u8>,
1339 ValidityError<&[u8], bool>,
1340 > = ConvertError::Size(SizeError::new(&[0u8]));
1341 let converted: ConvertError<Infallible, SizeError<&[u8], u8>, ValidityError<&[u8], bool>> =
1342 ConvertError::from(err);
1343 match converted {
1344 ConvertError::Size(_) => {}
1345 _ => panic!("Expected Size error"),
1346 }
1347 }
1348}