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}