runtime_capabilities/
handle.rs1use crate::CapabilityBound;
6use fidl::handle::{self, HandleBased};
7use fuchsia_sync::Mutex;
8use std::sync::Arc;
9
10#[derive(Debug, Clone)]
12pub struct Handle(Arc<Mutex<Option<handle::NullableHandle>>>);
13
14impl Handle {
15 pub fn new(handle: handle::NullableHandle) -> Self {
17 Self(Arc::new(Mutex::new(Some(handle))))
18 }
19
20 pub fn duplicate(&self) -> Option<handle::NullableHandle> {
23 self.0.lock().as_ref().and_then(|h| h.duplicate_handle(handle::Rights::SAME_RIGHTS).ok())
24 }
25
26 pub fn take(&self) -> Option<handle::NullableHandle> {
28 self.0.lock().take()
29 }
30}
31
32impl CapabilityBound for Handle {
33 fn debug_typename() -> &'static str {
34 "Handle"
35 }
36}
37
38impl Handle {
39 pub fn try_clone(&self) -> Result<Self, ()> {
40 self.duplicate().map(Self::new).ok_or(())
41 }
42}
43
44#[cfg(target_os = "fuchsia")]
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::fidl::IntoFsandboxCapability;
49 use crate::{Capability, WeakInstanceToken};
50 use assert_matches::assert_matches;
51 use fidl::handle::HandleBased;
52 use fidl_fuchsia_component_sandbox as fsandbox;
53
54 #[fuchsia::test]
56 async fn handle_into_fidl() {
57 let event = zx::Event::create();
58 let expected_koid = event.koid().unwrap();
59
60 let handle = Handle::new(event.into_handle());
61
62 let fidl_capability: fsandbox::Capability =
64 handle.into_fsandbox_capability(WeakInstanceToken::new_invalid());
65 assert_matches!(&fidl_capability, fsandbox::Capability::Handle(_));
66
67 let any: Capability = fidl_capability.try_into().unwrap();
68 let handle = assert_matches!(any, Capability::Handle(h) => h);
69
70 let handle: zx::NullableHandle = handle.take().unwrap();
72
73 let got_koid = handle.koid().unwrap();
75 assert_eq!(got_koid, expected_koid);
76 }
77
78 #[fuchsia::test]
80 async fn try_clone() {
81 let event = zx::Event::create();
82 let expected_koid = event.koid().unwrap();
83
84 let handle = Handle::new(event.into_handle());
85 let handle = handle.duplicate().unwrap();
86
87 let got_koid = handle.koid().unwrap();
88 assert_eq!(got_koid, expected_koid);
89
90 let (ch, _) = zx::Channel::create();
91 let handle = Handle::new(ch.into_handle());
92 assert_matches!(handle.try_clone(), Err(()));
93 }
94}