1use core::fmt;
6use core::mem::MaybeUninit;
7
8use crate::{
9 Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, Encoder, EncoderExt,
10 FromWire, FromWireRef, IntoNatural, Slot, ValidationError, Wire, wire,
11};
12
13#[repr(u8)]
19#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
20pub enum Unit {
21 #[default]
23 Unit = 0,
24}
25
26impl Constrained for Unit {
27 type Constraint = ();
28
29 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
30 Ok(())
31 }
32}
33
34unsafe impl Wire for Unit {
36 type Narrowed<'de> = Self;
37
38 #[inline]
39 fn zero_padding(_: &mut MaybeUninit<Self>) {}
40}
41
42impl fmt::Debug for Unit {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 f.debug_struct("Unit").finish()
45 }
46}
47
48impl fmt::Display for Unit {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(f, "Unit")
51 }
52}
53
54unsafe impl<D: ?Sized> Decode<D> for Unit {
56 fn decode(
57 slot: Slot<'_, Self>,
58 _: &mut D,
59 _: Self::Constraint,
60 ) -> Result<(), crate::DecodeError> {
61 let value = unsafe { slot.as_ptr().cast::<u8>().read() };
63 match value {
64 0 => Ok(()),
65 invalid => Err(DecodeError::InvalidUnit(invalid)),
66 }
67 }
68}
69
70unsafe impl<E: ?Sized> Encode<Unit, E> for () {
72 fn encode(self, _: &mut E, out: &mut MaybeUninit<Unit>, _: ()) -> Result<(), EncodeError> {
73 let _ = out.write(Unit::Unit);
74 Ok(())
75 }
76}
77
78unsafe impl<E: ?Sized> Encode<Unit, E> for &() {
80 fn encode(
81 self,
82 encoder: &mut E,
83 out: &mut MaybeUninit<Unit>,
84 constraint: (),
85 ) -> Result<(), EncodeError> {
86 Encode::encode((), encoder, out, constraint)
87 }
88}
89
90unsafe impl<E> EncodeOption<wire::Box<'static, Unit>, E> for ()
92where
93 E: Encoder + ?Sized,
94{
95 #[inline]
96 fn encode_option(
97 this: Option<Self>,
98 encoder: &mut E,
99 out: &mut MaybeUninit<wire::Box<'static, Unit>>,
100 constraint: (),
101 ) -> Result<(), EncodeError> {
102 if let Some(value) = this {
103 encoder.encode_next_with_constraint(value, constraint)?;
104 wire::Box::encode_present(out);
105 } else {
106 wire::Box::encode_absent(out);
107 }
108
109 Ok(())
110 }
111}
112
113unsafe impl<E> EncodeOption<wire::Box<'static, Unit>, E> for &()
115where
116 E: Encoder + ?Sized,
117{
118 #[inline]
119 fn encode_option(
120 this: Option<Self>,
121 encoder: &mut E,
122 out: &mut MaybeUninit<wire::Box<'static, Unit>>,
123 constraint: (),
124 ) -> Result<(), EncodeError> {
125 <()>::encode_option(this.cloned(), encoder, out, constraint)
126 }
127}
128
129impl From<()> for Unit {
130 fn from(_: ()) -> Self {
131 Self::Unit
132 }
133}
134
135impl<'a> From<&'a ()> for Unit {
136 fn from(_: &'a ()) -> Self {
137 Self::Unit
138 }
139}
140
141impl From<Unit> for () {
142 fn from(_: Unit) -> Self {}
143}
144
145impl<'a> From<&'a Unit> for () {
146 fn from(_: &'a Unit) -> Self {}
147}
148
149impl FromWire<Unit> for () {
150 fn from_wire(wire: Unit) -> Self {
151 Self::from_wire_ref(&wire)
152 }
153}
154
155impl FromWireRef<Unit> for () {
156 fn from_wire_ref(_: &Unit) -> Self {}
157}
158
159impl IntoNatural for Unit {
160 type Natural = ();
161}
162
163#[cfg(test)]
164mod tests {
165 use crate::{DecoderExt as _, EncoderExt as _, chunks, wire};
166
167 #[test]
168 fn decode_unit() {
169 assert_eq!(
170 chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
171 .as_mut_slice()
172 .decode::<wire::Unit>()
173 .unwrap(),
174 wire::Unit::Unit,
175 );
176 }
177
178 #[test]
179 fn encode_unit() {
180 assert_eq!(
181 Vec::encode(()).unwrap(),
182 chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
183 );
184 }
185}