Skip to main content

fidl_next_protocol/wire/
strict.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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/// A strict FIDL message.
14#[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    /// Consumes the `Strict`, returning the contained value.
61    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}