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