zx/channel/
message_buf.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 crate::{Handle, HandleInfo, ObjectType, Rights};
6
7/// A buffer for _receiving_ messages from a channel.
8///
9/// A `MessageBuf` is essentially a byte buffer and a vector of
10/// handles, but move semantics for "taking" handles requires special handling.
11///
12/// Note that for sending messages to a channel, the caller manages the buffers,
13/// using a plain byte slice and `Vec<Handle>`.
14#[derive(Debug, Default)]
15pub struct MessageBuf {
16    pub(super) bytes: Vec<u8>,
17    pub(super) handles: Vec<Handle>,
18}
19
20impl MessageBuf {
21    /// Create a new, empty, message buffer.
22    pub fn new() -> Self {
23        Default::default()
24    }
25
26    /// Create a new non-empty message buffer.
27    pub fn new_with(v: Vec<u8>, h: Vec<Handle>) -> Self {
28        Self { bytes: v, handles: h }
29    }
30
31    /// Splits apart the message buf into a vector of bytes and a vector of handles.
32    pub fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<Handle>) {
33        (&mut self.bytes, &mut self.handles)
34    }
35
36    /// Splits apart the message buf into a vector of bytes and a vector of handles.
37    pub fn split(self) -> (Vec<u8>, Vec<Handle>) {
38        (self.bytes, self.handles)
39    }
40
41    /// Ensure that the buffer has the capacity to hold at least `n_bytes` bytes.
42    pub fn ensure_capacity_bytes(&mut self, n_bytes: usize) {
43        ensure_capacity(&mut self.bytes, n_bytes);
44    }
45
46    /// Ensure that the buffer has the capacity to hold at least `n_handles` handles.
47    pub fn ensure_capacity_handles(&mut self, n_handles: usize) {
48        ensure_capacity(&mut self.handles, n_handles);
49    }
50
51    /// Ensure that at least n_bytes bytes are initialized (0 fill).
52    pub fn ensure_initialized_bytes(&mut self, n_bytes: usize) {
53        if n_bytes <= self.bytes.len() {
54            return;
55        }
56        self.bytes.resize(n_bytes, 0);
57    }
58
59    /// Ensure that the allocation for the message's bytes is as small as possible.
60    pub fn shrink_bytes_to_fit(&mut self) {
61        self.bytes.shrink_to_fit();
62    }
63
64    /// Get a reference to the bytes of the message buffer, as a `&[u8]` slice.
65    pub fn bytes(&self) -> &[u8] {
66        self.bytes.as_slice()
67    }
68
69    /// The number of handles in the message buffer. Note this counts the number
70    /// available when the message was received; `take_handle` does not affect
71    /// the count.
72    pub fn n_handles(&self) -> usize {
73        self.handles.len()
74    }
75
76    /// Take the handle at the specified index from the message buffer. If the
77    /// method is called again with the same index, it will return `None`, as
78    /// will happen if the index exceeds the number of handles available.
79    pub fn take_handle(&mut self, index: usize) -> Option<Handle> {
80        self.handles.get_mut(index).and_then(|handle| {
81            if handle.is_invalid() {
82                None
83            } else {
84                Some(std::mem::replace(handle, Handle::invalid()))
85            }
86        })
87    }
88
89    /// Clear the bytes and handles contained in the buf. This will drop any
90    /// contained handles, resulting in their resources being freed.
91    pub fn clear(&mut self) {
92        self.bytes.clear();
93        self.handles.clear();
94    }
95}
96
97/// A buffer for _receiving_ messages from a channel.
98///
99/// This differs from `MessageBuf` in that it holds `HandleInfo` with
100/// extended handle information.
101///
102/// A `MessageBufEtc` is essentially a byte buffer and a vector of handle
103/// infos, but move semantics for "taking" handles requires special handling.
104///
105/// Note that for sending messages to a channel, the caller manages the buffers,
106/// using a plain byte slice and `Vec<HandleDisposition>`.
107#[derive(Debug, Default)]
108pub struct MessageBufEtc {
109    pub(super) bytes: Vec<u8>,
110    pub(super) handle_infos: Vec<HandleInfo>,
111}
112
113impl MessageBufEtc {
114    /// Create a new, empty, message buffer.
115    pub fn new() -> Self {
116        Default::default()
117    }
118
119    /// Create a new non-empty message buffer.
120    pub fn new_with(v: Vec<u8>, h: Vec<HandleInfo>) -> Self {
121        Self { bytes: v, handle_infos: h }
122    }
123
124    /// Splits apart the message buf into a vector of bytes and a vector of handle infos.
125    pub fn split_mut(&mut self) -> (&mut Vec<u8>, &mut Vec<HandleInfo>) {
126        (&mut self.bytes, &mut self.handle_infos)
127    }
128
129    /// Splits apart the message buf into a vector of bytes and a vector of handle infos.
130    pub fn split(self) -> (Vec<u8>, Vec<HandleInfo>) {
131        (self.bytes, self.handle_infos)
132    }
133
134    /// Ensure that the buffer has the capacity to hold at least `n_bytes` bytes.
135    pub fn ensure_capacity_bytes(&mut self, n_bytes: usize) {
136        ensure_capacity(&mut self.bytes, n_bytes);
137    }
138
139    /// Ensure that the buffer has the capacity to hold at least `n_handles` handle infos.
140    pub fn ensure_capacity_handle_infos(&mut self, n_handle_infos: usize) {
141        ensure_capacity(&mut self.handle_infos, n_handle_infos);
142    }
143
144    /// Ensure that at least n_bytes bytes are initialized (0 fill).
145    pub fn ensure_initialized_bytes(&mut self, n_bytes: usize) {
146        if n_bytes <= self.bytes.len() {
147            return;
148        }
149        self.bytes.resize(n_bytes, 0);
150    }
151
152    /// Ensure that the allocation for the message's bytes is as small as possible.
153    pub fn shrink_bytes_to_fit(&mut self) {
154        self.bytes.shrink_to_fit();
155    }
156
157    /// Get a reference to the bytes of the message buffer, as a `&[u8]` slice.
158    pub fn bytes(&self) -> &[u8] {
159        self.bytes.as_slice()
160    }
161
162    /// The number of handles in the message buffer. Note this counts the number
163    /// available when the message was received; `take_handle` does not affect
164    /// the count.
165    pub fn n_handle_infos(&self) -> usize {
166        self.handle_infos.len()
167    }
168
169    /// Take the handle at the specified index from the message buffer. If the
170    /// method is called again with the same index, it will return `None`, as
171    /// will happen if the index exceeds the number of handles available.
172    pub fn take_handle_info(&mut self, index: usize) -> Option<HandleInfo> {
173        self.handle_infos.get_mut(index).and_then(|handle_info| {
174            if handle_info.handle.is_invalid() {
175                None
176            } else {
177                Some(std::mem::replace(
178                    handle_info,
179                    HandleInfo {
180                        handle: Handle::invalid(),
181                        object_type: ObjectType::NONE,
182                        rights: Rights::NONE,
183                        _unused: 0,
184                    },
185                ))
186            }
187        })
188    }
189
190    /// Clear the bytes and handles contained in the buf. This will drop any
191    /// contained handles, resulting in their resources being freed.
192    pub fn clear(&mut self) {
193        self.bytes.clear();
194        self.handle_infos.clear();
195    }
196}
197
198pub(crate) fn ensure_capacity<T>(vec: &mut Vec<T>, size: usize) {
199    let len = vec.len();
200    if size > len {
201        vec.reserve(size - len);
202    }
203}