1use crate::Endian;
13#[cfg(not(feature = "std"))]
14use alloc::{boxed::Box, vec::Vec};
15use core::marker::PhantomData;
16
17pub trait ReadMagic {
22 type MagicType;
24
25 const MAGIC: Self::MagicType;
27}
28
29pub trait WriteMagic {
34 type MagicType;
36
37 const MAGIC: Self::MagicType;
39}
40
41pub trait ReadEndian {
46 const ENDIAN: EndianKind;
48}
49
50pub trait WriteEndian {
55 const ENDIAN: EndianKind;
57}
58
59#[derive(Clone, Copy, Debug, Eq, PartialEq)]
61pub enum EndianKind {
62 None,
64 Endian(Endian),
66 Runtime,
69 Mixed,
71}
72
73impl EndianKind {
74 #[must_use]
76 pub fn endian(self) -> Option<Endian> {
77 match self {
78 EndianKind::None | EndianKind::Runtime | EndianKind::Mixed => None,
79 EndianKind::Endian(endian) => Some(endian),
80 }
81 }
82}
83
84macro_rules! endian_impl {
85 ($($($Ty:ty)+ => $kind:expr),+ $(,)?) => {$($(
86 impl ReadEndian for $Ty {
87 const ENDIAN: EndianKind = $kind;
88 }
89
90 impl WriteEndian for $Ty {
91 const ENDIAN: EndianKind = $kind;
92 }
93 )+)+}
94}
95
96endian_impl!(() i8 u8 core::num::NonZeroU8 core::num::NonZeroI8 crate::strings::NullString => EndianKind::None);
97
98impl<T: ReadEndian + ?Sized> ReadEndian for Box<T> {
99 const ENDIAN: EndianKind = <T as ReadEndian>::ENDIAN;
100}
101
102impl<T: WriteEndian + ?Sized> WriteEndian for Box<T> {
103 const ENDIAN: EndianKind = <T as WriteEndian>::ENDIAN;
104}
105
106impl<T: ReadEndian> ReadEndian for [T] {
107 const ENDIAN: EndianKind = <T as ReadEndian>::ENDIAN;
108}
109
110impl<T: WriteEndian> WriteEndian for [T] {
111 const ENDIAN: EndianKind = <T as WriteEndian>::ENDIAN;
112}
113
114impl<T: ReadEndian, const N: usize> ReadEndian for [T; N] {
115 const ENDIAN: EndianKind = <T as ReadEndian>::ENDIAN;
116}
117
118impl<T: WriteEndian, const N: usize> WriteEndian for [T; N] {
119 const ENDIAN: EndianKind = <T as WriteEndian>::ENDIAN;
120}
121
122macro_rules! endian_generic_impl {
123 ($($Ty:ident)+) => {$(
124 impl<T: ReadEndian> ReadEndian for $Ty<T> {
125 const ENDIAN: EndianKind = <T as ReadEndian>::ENDIAN;
126 }
127
128 impl<T: WriteEndian> WriteEndian for $Ty<T> {
129 const ENDIAN: EndianKind = <T as WriteEndian>::ENDIAN;
130 }
131 )+}
132}
133
134endian_generic_impl!(Option Vec PhantomData);
135
136macro_rules! endian_tuple_impl {
137 ($type1:ident $(, $types:ident)*) => {
138 #[allow(non_camel_case_types)]
139 impl<$type1: ReadEndian, $($types: ReadEndian),*> ReadEndian for ($type1, $($types),*) {
140 const ENDIAN: EndianKind = EndianKind::Mixed;
141 }
142
143 #[allow(non_camel_case_types)]
144 impl<$type1: WriteEndian, $($types: WriteEndian),*> WriteEndian for ($type1, $($types),*) {
145 const ENDIAN: EndianKind = EndianKind::Mixed;
146 }
147
148 endian_tuple_impl!($($types),*);
149 };
150
151 () => {};
152}
153
154endian_tuple_impl!(
155 b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21,
156 b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32
157);