Skip to main content

fidl_next_protocol/wire/
message_header.rs

1// Copyright 2024 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;
6
7use fidl_constants::MAGIC_NUMBER_INITIAL;
8use fidl_next_codec::{
9    Constrained, Decode, DecodeError, Encode, EncodeError, Slot, ValidationError, Wire, bitflags,
10    wire,
11};
12use zerocopy::IntoBytes;
13
14use crate::Flexibility;
15
16/// The transactional message header flags in byte 0.
17#[derive(Clone, Copy, Debug, IntoBytes)]
18#[repr(transparent)]
19pub struct MessageHeaderFlags0(u8);
20
21/// The transactional message header flags in byte 1.
22#[derive(Clone, Copy, Debug, IntoBytes)]
23#[repr(transparent)]
24pub struct MessageHeaderFlags1(u8);
25
26/// The transactional message header flags in byte 2.
27#[derive(Clone, Copy, Debug, IntoBytes)]
28#[repr(transparent)]
29pub struct MessageHeaderFlags2(u8);
30
31bitflags::bitflags! {
32    impl MessageHeaderFlags0: u8 {
33        /// The bit set to indicate that the FIDL wire format is version 2.
34        const WIRE_FORMAT_V2 = 1 << 1;
35    }
36
37    impl MessageHeaderFlags1: u8 {
38    }
39
40    impl MessageHeaderFlags2: u8 {
41        /// The bit set to indicate that the FIDL method is flexible.
42        const FLEXIBLE_METHOD = 1 << 7;
43    }
44}
45
46/// A FIDL protocol message header
47#[derive(Clone, Copy, Debug, IntoBytes)]
48#[repr(C)]
49pub struct MessageHeader {
50    /// The transaction ID of the message header
51    pub txid: wire::Uint32,
52    /// Flags byte 0
53    pub flags_0: MessageHeaderFlags0,
54    /// Flags byte 1
55    pub flags_1: MessageHeaderFlags1,
56    /// Flags byte 2
57    pub flags_2: MessageHeaderFlags2,
58    /// Magic number
59    pub magic_number: u8,
60    /// The ordinal of the message following this header
61    pub ordinal: wire::Uint64,
62}
63
64impl MessageHeader {
65    /// Returns a new message header with the given transaction ID, ordinal, and
66    /// flexibility.
67    pub fn new(txid: u32, ordinal: u64, flexibility: Flexibility) -> Self {
68        Self {
69            txid: wire::Uint32(txid),
70            flags_0: MessageHeaderFlags0::WIRE_FORMAT_V2,
71            flags_1: MessageHeaderFlags1::empty(),
72            flags_2: match flexibility {
73                Flexibility::Strict => MessageHeaderFlags2::empty(),
74                Flexibility::Flexible => MessageHeaderFlags2::FLEXIBLE_METHOD,
75            },
76            magic_number: MAGIC_NUMBER_INITIAL,
77            ordinal: wire::Uint64(ordinal),
78        }
79    }
80
81    /// Returns the flexibility of the message header.
82    pub fn flexibility(&self) -> Flexibility {
83        if self.flags_2.contains(MessageHeaderFlags2::FLEXIBLE_METHOD) {
84            Flexibility::Flexible
85        } else {
86            Flexibility::Strict
87        }
88    }
89}
90
91impl Constrained for MessageHeader {
92    type Constraint = ();
93
94    fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
95        Ok(())
96    }
97}
98
99unsafe impl Wire for MessageHeader {
100    type Narrowed<'de> = Self;
101
102    #[inline]
103    fn zero_padding(_: &mut MaybeUninit<Self>) {
104        // Wire message headers have no padding
105    }
106}
107
108unsafe impl<E: ?Sized> Encode<MessageHeader, E> for MessageHeader {
109    #[inline]
110    fn encode(
111        self,
112        _: &mut E,
113        out: &mut MaybeUninit<MessageHeader>,
114        _: (),
115    ) -> Result<(), EncodeError> {
116        out.write(self);
117        Ok(())
118    }
119}
120
121unsafe impl<E: ?Sized> Encode<MessageHeader, E> for &MessageHeader {
122    #[inline]
123    fn encode(
124        self,
125        encoder: &mut E,
126        out: &mut MaybeUninit<MessageHeader>,
127        constraint: (),
128    ) -> Result<(), EncodeError> {
129        Encode::encode(*self, encoder, out, constraint)
130    }
131}
132
133unsafe impl<D: ?Sized> Decode<D> for MessageHeader {
134    #[inline]
135    fn decode(_: Slot<'_, Self>, _: &mut D, _: ()) -> Result<(), DecodeError> {
136        Ok(())
137    }
138}