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 unsafe fn parse_step<const ALIGNED: bool>(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
64 let (_value, remainder) = unsafe { Data::parse_step::<false>(bytes) }?;
67 let value = unsafe { bytes.as_ptr().cast::<Unaligned<Self>>().as_ref_unchecked() };
71 Some((value, remainder))
72 }
73}
74
75unsafe impl<Data> AnyBitPatternMarker for Unaligned<Data> where
77 Data: TrivialType + AnyBitPatternMarker
78{
79}
80
81#[cfg(feature = "scale-codec")]
82impl<Data> Encode for Unaligned<Data>
83where
84 Data: TrivialType + Encode,
85{
86 #[inline(always)]
87 fn size_hint(&self) -> usize {
88 let inner = self.0;
89 inner.size_hint()
90 }
91
92 #[inline(always)]
93 fn encode_to<T>(&self, dest: &mut T)
94 where
95 T: Output + ?Sized,
96 {
97 let inner = self.0;
98 inner.encode_to(dest);
99 }
100
101 #[inline(always)]
102 fn using_encoded<R, F>(&self, f: F) -> R
103 where
104 F: FnOnce(&[u8]) -> R,
105 {
106 let inner = self.0;
107 inner.using_encoded(f)
108 }
109}
110
111#[cfg(feature = "scale-codec")]
112impl<Data> EncodeLike for Unaligned<Data> where Data: TrivialType + Encode {}
113
114#[cfg(feature = "serde")]
115impl<Data> Serialize for Unaligned<Data>
116where
117 Data: TrivialType + Serialize,
118{
119 #[inline(always)]
120 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
121 where
122 S: Serializer,
123 {
124 let inner = self.0;
125 inner.serialize(serializer)
126 }
127}
128
129impl<Data> Unaligned<Data>
130where
131 Data: TrivialType,
132{
133 #[inline(always)]
135 pub const fn new(inner: Data) -> Self {
136 Self(inner)
137 }
138
139 #[inline(always)]
141 pub const fn as_inner(&self) -> Data {
142 self.0
143 }
144
145 pub const fn replace(&mut self, value: Data) {
147 self.0 = value;
148 }
149}