1use crate::alignment::Alignment;
2use crate::metadata::{IoTypeMetadataKind, MAX_METADATA_CAPACITY, concat_metadata_sources};
3use crate::trivial_type::{AnyBitPatternMarker, TrivialType};
4use core::fmt;
5#[cfg(feature = "scale-codec")]
6use parity_scale_codec::{Decode, Encode, EncodeLike, MaxEncodedLen, Output};
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize, Serializer};
9
10#[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
17#[cfg_attr(feature = "scale-codec", derive(Decode, MaxEncodedLen))]
18#[cfg_attr(feature = "serde", derive(Deserialize))]
19#[cfg_attr(feature = "serde", serde(transparent))]
20#[repr(C, packed)]
21pub struct Unaligned<Data>(Data)
22where
23 Data: TrivialType;
24
25const impl<Data> From<Data> for Unaligned<Data>
26where
27 Data: TrivialType,
28{
29 #[inline(always)]
30 fn from(value: Data) -> Self {
31 Self(value)
32 }
33}
34
35impl<Data> fmt::Display for Unaligned<Data>
36where
37 Data: TrivialType + fmt::Display,
38{
39 #[inline]
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 let inner = self.0;
42 inner.fmt(f)
43 }
44}
45
46unsafe impl<Data> TrivialType for Unaligned<Data>
48where
49 Data: TrivialType,
50{
51 const ALIGNMENT: Alignment = u8::ALIGNMENT;
52 const METADATA: &[u8] = {
53 const fn metadata(inner_metadata: &[u8]) -> ([u8; MAX_METADATA_CAPACITY], usize) {
54 concat_metadata_sources(&[&[IoTypeMetadataKind::Unaligned as u8], inner_metadata])
55 }
56
57 let (metadata_scratch, metadata_size) = &metadata(Data::METADATA);
59 metadata_scratch.split_at(*metadata_size).0
60 };
61
62 #[inline(always)]
63 fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
64 let (_value, remainder) = Data::try_from_bytes_unaligned(bytes)?;
65 let value = unsafe { bytes.as_ptr().cast::<Unaligned<Self>>().as_ref_unchecked() };
69 Some((value, remainder))
70 }
71}
72
73unsafe impl<Data> AnyBitPatternMarker for Unaligned<Data> where
75 Data: TrivialType + AnyBitPatternMarker
76{
77}
78
79#[cfg(feature = "scale-codec")]
80impl<Data> Encode for Unaligned<Data>
81where
82 Data: TrivialType + Encode,
83{
84 #[inline(always)]
85 fn size_hint(&self) -> usize {
86 let inner = self.0;
87 inner.size_hint()
88 }
89
90 #[inline(always)]
91 fn encode_to<T>(&self, dest: &mut T)
92 where
93 T: Output + ?Sized,
94 {
95 let inner = self.0;
96 inner.encode_to(dest);
97 }
98
99 #[inline(always)]
100 fn using_encoded<R, F>(&self, f: F) -> R
101 where
102 F: FnOnce(&[u8]) -> R,
103 {
104 let inner = self.0;
105 inner.using_encoded(f)
106 }
107}
108
109#[cfg(feature = "scale-codec")]
110impl<Data> EncodeLike for Unaligned<Data> where Data: TrivialType + Encode {}
111
112#[cfg(feature = "serde")]
113impl<Data> Serialize for Unaligned<Data>
114where
115 Data: TrivialType + Serialize,
116{
117 #[inline(always)]
118 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
119 where
120 S: Serializer,
121 {
122 let inner = self.0;
123 inner.serialize(serializer)
124 }
125}
126
127impl<Data> Unaligned<Data>
128where
129 Data: TrivialType,
130{
131 #[inline(always)]
133 pub const fn new(inner: Data) -> Self {
134 Self(inner)
135 }
136
137 #[inline(always)]
139 pub const fn as_inner(&self) -> Data {
140 self.0
141 }
142
143 pub const fn replace(&mut self, value: Data) {
145 self.0 = value;
146 }
147}