1use fidl::encoding::{Context, Decode, Decoder, DefaultFuchsiaResourceDialect, TypeMarker};
8use fidl::{AsHandleRef, Handle, HandleBased, HandleDisposition, HandleInfo, HandleOp, Rights};
9use zx_status::Status;
10use zx_types;
11
12pub enum HandleSubtype {
15 Event,
16 Channel,
17}
18
19impl HandleSubtype {
20 fn obj_type(&self) -> zx_types::zx_obj_type_t {
21 match self {
22 HandleSubtype::Event => zx_types::ZX_OBJ_TYPE_EVENT,
23 HandleSubtype::Channel => zx_types::ZX_OBJ_TYPE_CHANNEL,
24 }
25 }
26}
27
28pub struct HandleDef {
31 pub subtype: HandleSubtype,
32 pub rights: Rights,
33}
34
35pub fn create_handles(defs: &[HandleDef]) -> Vec<zx_types::zx_handle_info_t> {
38 let mut factory: HandleFactory = Default::default();
39 let mut handle_infos = Vec::with_capacity(defs.len());
40 for def in defs {
41 let default_rights_handle = match def.subtype {
42 HandleSubtype::Event => factory.create_event().unwrap().into_handle(),
43 HandleSubtype::Channel => factory.create_channel().unwrap().into_handle(),
44 };
45 handle_infos.push(zx_types::zx_handle_info_t {
46 handle: match def.rights {
47 Rights::SAME_RIGHTS => default_rights_handle,
48 rights => default_rights_handle.replace(rights).unwrap(),
49 }
50 .into_raw(),
51 ty: def.subtype.obj_type(),
52 rights: def.rights.bits(),
53 unused: 0,
54 });
55 }
56 handle_infos
57}
58
59#[derive(Default)]
62struct HandleFactory {
63 extra_channel: Option<fidl::Channel>,
64}
65
66impl HandleFactory {
70 fn create_event(&mut self) -> Result<fidl::Event, Status> {
71 Ok(fidl::Event::create())
72 }
73
74 fn create_channel(&mut self) -> Result<fidl::Channel, Status> {
75 match self.extra_channel.take() {
76 Some(channel) => Ok(channel),
77 None => {
78 let (c1, c2) = fidl::Channel::create();
79 self.extra_channel = Some(c2);
80 Ok(c1)
81 }
82 }
83 }
84}
85
86pub fn copy_handle<T: HandleBased>(handle_info: &zx_types::zx_handle_info_t) -> T {
88 T::from_handle(unsafe { Handle::from_raw(handle_info.handle) })
92}
93
94pub fn select_raw_handle_infos(
96 handle_defs: &[zx_types::zx_handle_info_t],
97 indices: &[usize],
98) -> Vec<zx_types::zx_handle_info_t> {
99 indices.iter().map(|&i| handle_defs[i]).collect()
100}
101
102pub fn select_handle_infos(
105 handle_defs: &[zx_types::zx_handle_info_t],
106 indices: &[usize],
107) -> Vec<HandleInfo> {
108 indices.iter().map(|&i| unsafe { HandleInfo::from_raw(handle_defs[i]) }).collect()
112}
113
114pub fn get_handle_koid(handle_info: &zx_types::zx_handle_info_t) -> zx_types::zx_koid_t {
117 let handle = std::mem::ManuallyDrop::new(unsafe { Handle::from_raw(handle_info.handle) });
121 handle.basic_info().unwrap().koid.raw_koid()
122}
123
124pub fn to_zx_handle_disposition_t(
126 mut hd: HandleDisposition<'_>,
127) -> zx_types::zx_handle_disposition_t {
128 match hd.take_op() {
129 HandleOp::Move(handle) => zx_types::zx_handle_disposition_t {
130 operation: zx_types::ZX_HANDLE_OP_MOVE,
131 handle: handle.raw_handle(),
132 type_: hd.object_type.into_raw(),
133 rights: hd.rights.bits(),
134 result: hd.result.into_raw(),
135 },
136 HandleOp::Duplicate(handle_ref) => zx_types::zx_handle_disposition_t {
137 operation: zx_types::ZX_HANDLE_OP_DUPLICATE,
138 handle: handle_ref.raw_handle(),
139 type_: hd.object_type.into_raw(),
140 rights: hd.rights.bits(),
141 result: hd.result.into_raw(),
142 },
143 }
144}
145
146#[cfg(target_os = "fuchsia")]
156pub fn get_info_handle_valid(handle_info: &zx_types::zx_handle_info_t) -> Result<(), Status> {
157 use zx::sys;
158 Status::ok(unsafe {
159 sys::zx_object_get_info(
160 handle_info.handle,
161 sys::ZX_INFO_HANDLE_VALID,
162 std::ptr::null_mut(),
163 0,
164 std::ptr::null_mut(),
165 std::ptr::null_mut(),
166 )
167 })
168}
169
170#[cfg(not(target_os = "fuchsia"))]
171pub fn get_info_handle_valid(handle_info: &zx_types::zx_handle_info_t) -> Result<(), Status> {
172 use fidl::EmulatedHandleRef;
173 let handle = std::mem::ManuallyDrop::new(unsafe { Handle::from_raw(handle_info.handle) });
177 if handle.is_invalid() || handle.is_dangling() {
181 Err(Status::BAD_HANDLE)
182 } else {
183 Ok(())
184 }
185}
186
187pub fn repeat<T: Clone>(value: T, len: usize) -> Vec<T> {
189 std::iter::repeat(value).take(len).collect::<Vec<_>>()
190}
191
192pub fn decode_value<T: TypeMarker>(
194 context: Context,
195 bytes: &[u8],
196 handles: &mut [HandleInfo],
197) -> T::Owned
198where
199 T::Owned: Decode<T, DefaultFuchsiaResourceDialect>,
200{
201 let mut value = T::Owned::new_empty();
202 Decoder::decode_with_context::<T>(context, bytes, handles, &mut value).expect(
203 "failed decoding for the GIDL decode() function (not a regular decode test failure!)",
204 );
205 value
206}