1use core::mem::MaybeUninit;
6use core::ops::Deref;
7
8use fidl_next_codec::{
9 Constrained, Decode, DecodeError, Encode, EncodeError, Encoder, FromWire, FromWireRef,
10 IntoNatural, Slot, ValidationError, Wire, munge,
11};
12
13#[derive(Clone, Debug)]
15#[repr(transparent)]
16pub struct Strict<T> {
17 inner: T,
18}
19
20impl<T> Constrained for Strict<T>
21where
22 T: Constrained,
23{
24 type Constraint = T::Constraint;
25
26 fn validate(slot: Slot<'_, Self>, constraint: Self::Constraint) -> Result<(), ValidationError> {
27 munge!(let Self { inner } = slot);
28 T::validate(inner, constraint)
29 }
30}
31
32unsafe impl<T> Wire for Strict<T>
33where
34 T: Wire,
35{
36 type Narrowed<'de> = Strict<T::Narrowed<'de>>;
37
38 #[inline]
39 fn zero_padding(out: &mut MaybeUninit<Self>) {
40 munge!(let Self { inner } = out);
41 T::zero_padding(inner);
42 }
43}
44
45impl<T> Deref for Strict<T> {
46 type Target = T;
47
48 fn deref(&self) -> &Self::Target {
49 &self.inner
50 }
51}
52
53impl<T> AsRef<T> for Strict<T> {
54 fn as_ref(&self) -> &T {
55 Deref::deref(self)
56 }
57}
58
59impl<T> Strict<T> {
60 pub fn into_inner(self) -> T {
62 self.inner
63 }
64}
65
66unsafe impl<D, T> Decode<D> for Strict<T>
67where
68 D: ?Sized,
69 T: Decode<D>,
70{
71 fn decode(
72 slot: Slot<'_, Self>,
73 decoder: &mut D,
74 constraint: T::Constraint,
75 ) -> Result<(), DecodeError> {
76 munge!(let Self { inner } = slot);
77
78 T::decode(inner, decoder, constraint)
79 }
80}
81
82unsafe impl<E, W, T> Encode<Strict<W>, E> for crate::Strict<T>
83where
84 E: Encoder + ?Sized,
85 W: Wire,
86 T: Encode<W, E>,
87{
88 fn encode(
89 self,
90 encoder: &mut E,
91 out: &mut MaybeUninit<Strict<W>>,
92 constraint: W::Constraint,
93 ) -> Result<(), EncodeError> {
94 munge!(let Strict { inner } = out);
95 T::encode(self.0, encoder, inner, constraint)?;
96 Ok(())
97 }
98}
99
100unsafe impl<'a, E, W, T> Encode<Strict<W>, E> for &'a crate::Strict<T>
101where
102 E: Encoder + ?Sized,
103 W: Wire,
104 &'a T: Encode<W, E>,
105{
106 fn encode(
107 self,
108 encoder: &mut E,
109 out: &mut MaybeUninit<Strict<W>>,
110 constraint: W::Constraint,
111 ) -> Result<(), EncodeError> {
112 crate::Strict(self.as_ref()).encode(encoder, out, constraint)
113 }
114}
115
116impl<T, W> FromWire<Strict<W>> for crate::Strict<T>
117where
118 T: FromWire<W>,
119{
120 #[inline]
121 fn from_wire(wire: Strict<W>) -> Self {
122 crate::Strict(T::from_wire(wire.inner))
123 }
124}
125
126impl<T: IntoNatural> IntoNatural for Strict<T> {
127 type Natural = crate::Strict<T::Natural>;
128}
129
130impl<T, W> FromWireRef<Strict<W>> for crate::Strict<T>
131where
132 T: FromWireRef<W>,
133{
134 #[inline]
135 fn from_wire_ref(wire: &Strict<W>) -> Self {
136 crate::Strict(T::from_wire_ref(wire.as_ref()))
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::Strict;
143
144 use fidl_next_codec::{DecoderExt as _, EncoderExt as _, chunks, wire};
145
146 #[test]
147 fn encode_strict() {
148 assert_eq!(
149 Vec::encode(crate::Strict::<i32>(0x12345678)).unwrap(),
150 chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00],
151 );
152 }
153
154 #[test]
155 fn decode_strict() {
156 assert_eq!(
157 chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00]
158 .as_mut_slice()
159 .decode::<Strict<wire::Int32>>()
160 .unwrap()
161 .as_ref()
162 .0,
163 0x12345678,
164 );
165 }
166}