1use fidl::encoding::{Context, Decode, Decoder, DefaultFuchsiaResourceDialect, TypeMarker};
8use fidl::{
9 AsHandleRef, HandleBased, HandleDisposition, HandleInfo, HandleOp, NullableHandle, Rights,
10};
11use zx_status::Status;
12use zx_types;
13
14pub enum HandleSubtype {
17 Event,
18 Channel,
19}
20
21impl HandleSubtype {
22 fn obj_type(&self) -> zx_types::zx_obj_type_t {
23 match self {
24 HandleSubtype::Event => zx_types::ZX_OBJ_TYPE_EVENT,
25 HandleSubtype::Channel => zx_types::ZX_OBJ_TYPE_CHANNEL,
26 }
27 }
28}
29
30pub struct HandleDef {
33 pub subtype: HandleSubtype,
34 pub rights: Rights,
35}
36
37pub fn create_handles(defs: &[HandleDef]) -> Vec<zx_types::zx_handle_info_t> {
40 let mut factory: HandleFactory = Default::default();
41 let mut handle_infos = Vec::with_capacity(defs.len());
42 for def in defs {
43 let default_rights_handle = match def.subtype {
44 HandleSubtype::Event => factory.create_event().unwrap().into_handle(),
45 HandleSubtype::Channel => factory.create_channel().unwrap().into_handle(),
46 };
47 handle_infos.push(zx_types::zx_handle_info_t {
48 handle: match def.rights {
49 Rights::SAME_RIGHTS => default_rights_handle,
50 rights => default_rights_handle.replace(rights).unwrap(),
51 }
52 .into_raw(),
53 ty: def.subtype.obj_type(),
54 rights: def.rights.bits(),
55 unused: 0,
56 });
57 }
58 handle_infos
59}
60
61#[derive(Default)]
64struct HandleFactory {
65 extra_channel: Option<fidl::Channel>,
66}
67
68impl HandleFactory {
72 fn create_event(&mut self) -> Result<fidl::Event, Status> {
73 Ok(fidl::Event::create())
74 }
75
76 fn create_channel(&mut self) -> Result<fidl::Channel, Status> {
77 match self.extra_channel.take() {
78 Some(channel) => Ok(channel),
79 None => {
80 let (c1, c2) = fidl::Channel::create();
81 self.extra_channel = Some(c2);
82 Ok(c1)
83 }
84 }
85 }
86}
87
88pub fn copy_handle<T: HandleBased>(handle_info: &zx_types::zx_handle_info_t) -> T {
90 T::from_handle(unsafe { NullableHandle::from_raw(handle_info.handle) })
94}
95
96pub fn select_raw_handle_infos(
98 handle_defs: &[zx_types::zx_handle_info_t],
99 indices: &[usize],
100) -> Vec<zx_types::zx_handle_info_t> {
101 indices.iter().map(|&i| handle_defs[i]).collect()
102}
103
104pub fn select_handle_infos(
107 handle_defs: &[zx_types::zx_handle_info_t],
108 indices: &[usize],
109) -> Vec<HandleInfo> {
110 indices.iter().map(|&i| unsafe { HandleInfo::from_raw(handle_defs[i]) }).collect()
114}
115
116pub fn get_handle_koid(handle_info: &zx_types::zx_handle_info_t) -> zx_types::zx_koid_t {
119 let handle =
123 std::mem::ManuallyDrop::new(unsafe { NullableHandle::from_raw(handle_info.handle) });
124 handle.basic_info().unwrap().koid.raw_koid()
125}
126
127pub fn to_zx_handle_disposition_t(
129 mut hd: HandleDisposition<'_>,
130) -> zx_types::zx_handle_disposition_t {
131 match hd.take_op() {
132 HandleOp::Move(handle) => zx_types::zx_handle_disposition_t {
133 operation: zx_types::ZX_HANDLE_OP_MOVE,
134 handle: handle.raw_handle(),
135 type_: hd.object_type.into_raw(),
136 rights: hd.rights.bits(),
137 result: hd.result.into_raw(),
138 },
139 HandleOp::Duplicate(handle_ref) => zx_types::zx_handle_disposition_t {
140 operation: zx_types::ZX_HANDLE_OP_DUPLICATE,
141 handle: handle_ref.raw_handle(),
142 type_: hd.object_type.into_raw(),
143 rights: hd.rights.bits(),
144 result: hd.result.into_raw(),
145 },
146 }
147}
148
149#[cfg(target_os = "fuchsia")]
159pub fn get_info_handle_valid(handle_info: &zx_types::zx_handle_info_t) -> Result<(), Status> {
160 use zx::sys;
161 Status::ok(unsafe {
162 sys::zx_object_get_info(
163 handle_info.handle,
164 sys::ZX_INFO_HANDLE_VALID,
165 std::ptr::null_mut(),
166 0,
167 std::ptr::null_mut(),
168 std::ptr::null_mut(),
169 )
170 })
171}
172
173#[cfg(not(target_os = "fuchsia"))]
174pub fn get_info_handle_valid(handle_info: &zx_types::zx_handle_info_t) -> Result<(), Status> {
175 use fidl::EmulatedHandleRef;
176 let handle =
180 std::mem::ManuallyDrop::new(unsafe { NullableHandle::from_raw(handle_info.handle) });
181 if handle.is_invalid() || handle.is_dangling() { Err(Status::BAD_HANDLE) } else { Ok(()) }
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}