1#[cfg(fuchsia_api_level_at_least = "HEAD")]
9pub use everything::*;
10
11#[cfg(fuchsia_api_level_less_than = "HEAD")]
12mod everything {
13 use {
14 fidl as _, fidl_fuchsia_component_runtime as _, fidl_fuchsia_io as _,
15 fuchsia_component_client as _, futures as _, zx as _,
16 };
17
18 #[cfg(test)]
19 mod tests {
20 use assert_matches as _;
21 }
22}
23
24#[cfg(fuchsia_api_level_at_least = "HEAD")]
25mod everything {
26 use fidl::endpoints::{ServerEnd, create_proxy, create_request_stream};
27 use fuchsia_component_client::connect_to_protocol;
28 use futures::{Future, Stream};
29 use std::pin::{Pin, pin};
30 use std::task::{Context, Poll};
31 use zx::HandleBased;
32 use {fidl_fuchsia_component_runtime as fruntime, fidl_fuchsia_io as fio};
33
34 #[derive(Debug, PartialEq, Clone)]
36 pub enum DataValue {
37 Bytes(Vec<u8>),
38 String(String),
39 Int64(i64),
40 Uint64(u64),
41 }
42
43 impl From<Vec<u8>> for DataValue {
44 fn from(val: Vec<u8>) -> Self {
45 Self::Bytes(val)
46 }
47 }
48
49 impl From<String> for DataValue {
50 fn from(val: String) -> Self {
51 Self::String(val)
52 }
53 }
54
55 impl From<i64> for DataValue {
56 fn from(val: i64) -> Self {
57 Self::Int64(val)
58 }
59 }
60
61 impl From<u64> for DataValue {
62 fn from(val: u64) -> Self {
63 Self::Uint64(val)
64 }
65 }
66
67 impl TryFrom<fruntime::Data> for DataValue {
68 type Error = ();
69
70 fn try_from(val: fruntime::Data) -> Result<Self, Self::Error> {
71 match val {
72 fruntime::Data::Bytes(b) => Ok(Self::Bytes(b)),
73 fruntime::Data::String(b) => Ok(Self::String(b)),
74 fruntime::Data::Int64(b) => Ok(Self::Int64(b)),
75 fruntime::Data::Uint64(b) => Ok(Self::Uint64(b)),
76 _other_value => Err(()),
77 }
78 }
79 }
80
81 impl From<DataValue> for fruntime::Data {
82 fn from(val: DataValue) -> Self {
83 match val {
84 DataValue::Bytes(b) => Self::Bytes(b),
85 DataValue::String(b) => Self::String(b),
86 DataValue::Int64(b) => Self::Int64(b),
87 DataValue::Uint64(b) => Self::Uint64(b),
88 }
89 }
90 }
91
92 pub struct ConnectorReceiver {
94 pub stream: fruntime::ReceiverRequestStream,
95 }
96
97 impl Stream for ConnectorReceiver {
98 type Item = zx::Channel;
99
100 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
101 let pinned_stream = pin!(&mut self.stream);
102 match pinned_stream.poll_next(cx) {
103 Poll::Pending => Poll::Pending,
104 Poll::Ready(Some(Ok(fruntime::ReceiverRequest::Receive { channel, .. }))) => {
105 Poll::Ready(Some(channel))
106 }
107 _ => Poll::Ready(None),
108 }
109 }
110 }
111
112 pub struct DirConnectorReceiver {
114 pub stream: fruntime::DirReceiverRequestStream,
115 }
116
117 pub struct DirConnectorRequest {
118 pub channel: ServerEnd<fio::DirectoryMarker>,
119 pub path: String,
120 pub flags: fio::Flags,
121 }
122
123 impl Stream for DirConnectorReceiver {
124 type Item = DirConnectorRequest;
125
126 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
127 let pinned_stream = pin!(&mut self.stream);
128 match pinned_stream.poll_next(cx) {
129 Poll::Pending => Poll::Pending,
130 Poll::Ready(Some(Ok(fruntime::DirReceiverRequest::Receive {
131 channel,
132 path,
133 rights,
134 ..
135 }))) => Poll::Ready(Some(DirConnectorRequest { channel, path, flags: rights })),
136 _ => Poll::Ready(None),
137 }
138 }
139 }
140
141 #[derive(Debug, Clone)]
145 pub enum Capability {
146 Connector(Connector),
147 ConnectorRouter(ConnectorRouter),
148 Data(Data),
149 DataRouter(DataRouter),
150 Dictionary(Dictionary),
151 DictionaryRouter(DictionaryRouter),
152 DirConnector(DirConnector),
153 DirConnectorRouter(DirConnectorRouter),
154 InstanceToken(InstanceToken),
155 }
156
157 impl Capability {
158 pub fn from_raw_with_proxy(
159 capabilities_proxy: fruntime::CapabilitiesProxy,
160 handle: zx::EventPair,
161 type_: fruntime::CapabilityType,
162 ) -> Self {
163 match type_ {
164 fruntime::CapabilityType::Data => Self::Data(Data { handle, capabilities_proxy }),
165 fruntime::CapabilityType::Connector => {
166 Self::Connector(Connector { handle, capabilities_proxy })
167 }
168 fruntime::CapabilityType::DirConnector => {
169 Self::DirConnector(DirConnector { handle, capabilities_proxy })
170 }
171 fruntime::CapabilityType::Dictionary => {
172 Self::Dictionary(Dictionary { handle, capabilities_proxy })
173 }
174 fruntime::CapabilityType::DataRouter => {
175 Self::DataRouter(DataRouter { handle, capabilities_proxy })
176 }
177 fruntime::CapabilityType::ConnectorRouter => {
178 Self::ConnectorRouter(ConnectorRouter { handle, capabilities_proxy })
179 }
180 fruntime::CapabilityType::DirConnectorRouter => {
181 Self::DirConnectorRouter(DirConnectorRouter { handle, capabilities_proxy })
182 }
183 fruntime::CapabilityType::DictionaryRouter => {
184 Self::DictionaryRouter(DictionaryRouter { handle, capabilities_proxy })
185 }
186 fruntime::CapabilityType::InstanceToken => {
187 Self::InstanceToken(InstanceToken { handle })
188 }
189 other_type => panic!("unknown capability type: {other_type:?}"),
190 }
191 }
192
193 pub fn as_event_pair(&self) -> &zx::EventPair {
194 match self {
195 Self::Data(data) => &data.handle,
196 Self::Connector(connector) => &connector.handle,
197 Self::DirConnector(dir_connector) => &dir_connector.handle,
198 Self::Dictionary(dictionary) => &dictionary.handle,
199 Self::DataRouter(data_router) => &data_router.handle,
200 Self::ConnectorRouter(connector_router) => &connector_router.handle,
201 Self::DirConnectorRouter(dir_connector_router) => &dir_connector_router.handle,
202 Self::DictionaryRouter(dictionary_router) => &dictionary_router.handle,
203 Self::InstanceToken(instance_token) => &instance_token.handle,
204 }
205 }
206 }
207
208 impl From<Data> for Capability {
209 fn from(val: Data) -> Self {
210 Self::Data(val)
211 }
212 }
213
214 impl From<Connector> for Capability {
215 fn from(val: Connector) -> Self {
216 Self::Connector(val)
217 }
218 }
219
220 impl From<DirConnector> for Capability {
221 fn from(val: DirConnector) -> Self {
222 Self::DirConnector(val)
223 }
224 }
225
226 impl From<Dictionary> for Capability {
227 fn from(val: Dictionary) -> Self {
228 Self::Dictionary(val)
229 }
230 }
231
232 impl From<DataRouter> for Capability {
233 fn from(val: DataRouter) -> Self {
234 Self::DataRouter(val)
235 }
236 }
237
238 impl From<ConnectorRouter> for Capability {
239 fn from(val: ConnectorRouter) -> Self {
240 Self::ConnectorRouter(val)
241 }
242 }
243
244 impl From<DirConnectorRouter> for Capability {
245 fn from(val: DirConnectorRouter) -> Self {
246 Self::DirConnectorRouter(val)
247 }
248 }
249
250 impl From<DictionaryRouter> for Capability {
251 fn from(val: DictionaryRouter) -> Self {
252 Self::DictionaryRouter(val)
253 }
254 }
255
256 impl From<InstanceToken> for Capability {
257 fn from(val: InstanceToken) -> Self {
258 Self::InstanceToken(val)
259 }
260 }
261
262 impl TryFrom<Capability> for Data {
263 type Error = ();
264 fn try_from(val: Capability) -> Result<Self, Self::Error> {
265 match val {
266 Capability::Data(val) => Ok(val),
267 _ => Err(()),
268 }
269 }
270 }
271
272 impl TryFrom<Capability> for Connector {
273 type Error = ();
274 fn try_from(val: Capability) -> Result<Self, Self::Error> {
275 match val {
276 Capability::Connector(val) => Ok(val),
277 _ => Err(()),
278 }
279 }
280 }
281
282 impl TryFrom<Capability> for DirConnector {
283 type Error = ();
284 fn try_from(val: Capability) -> Result<Self, Self::Error> {
285 match val {
286 Capability::DirConnector(val) => Ok(val),
287 _ => Err(()),
288 }
289 }
290 }
291
292 impl TryFrom<Capability> for Dictionary {
293 type Error = ();
294 fn try_from(val: Capability) -> Result<Self, Self::Error> {
295 match val {
296 Capability::Dictionary(val) => Ok(val),
297 _ => Err(()),
298 }
299 }
300 }
301
302 impl TryFrom<Capability> for DataRouter {
303 type Error = ();
304 fn try_from(val: Capability) -> Result<Self, Self::Error> {
305 match val {
306 Capability::DataRouter(val) => Ok(val),
307 _ => Err(()),
308 }
309 }
310 }
311
312 impl TryFrom<Capability> for ConnectorRouter {
313 type Error = ();
314 fn try_from(val: Capability) -> Result<Self, Self::Error> {
315 match val {
316 Capability::ConnectorRouter(val) => Ok(val),
317 _ => Err(()),
318 }
319 }
320 }
321
322 impl TryFrom<Capability> for DirConnectorRouter {
323 type Error = ();
324 fn try_from(val: Capability) -> Result<Self, Self::Error> {
325 match val {
326 Capability::DirConnectorRouter(val) => Ok(val),
327 _ => Err(()),
328 }
329 }
330 }
331
332 impl TryFrom<Capability> for DictionaryRouter {
333 type Error = ();
334 fn try_from(val: Capability) -> Result<Self, Self::Error> {
335 match val {
336 Capability::DictionaryRouter(val) => Ok(val),
337 _ => Err(()),
338 }
339 }
340 }
341
342 impl TryFrom<Capability> for InstanceToken {
343 type Error = ();
344 fn try_from(val: Capability) -> Result<Self, Self::Error> {
345 match val {
346 Capability::InstanceToken(val) => Ok(val),
347 _ => Err(()),
348 }
349 }
350 }
351
352 #[derive(Debug)]
354 pub struct Data {
355 pub handle: zx::EventPair,
357
358 pub capabilities_proxy: fruntime::CapabilitiesProxy,
361 }
362
363 impl Data {
364 pub async fn new(value: DataValue) -> Self {
367 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
368 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
369 Self::new_with_proxy(proxy, value).await
370 }
371
372 pub async fn new_with_proxy(
374 capabilities_proxy: fruntime::CapabilitiesProxy,
375 value: DataValue,
376 ) -> Self {
377 let (handle, handle_other_end) = zx::EventPair::create();
378 capabilities_proxy
379 .data_create(handle_other_end, &value.into())
380 .await
381 .expect("failed to use fuchsia.component.runtime.Capabilities")
382 .expect(
383 "this should be impossible, we passed a valid handle with the correct rights",
384 );
385 Self { handle, capabilities_proxy }
386 }
387
388 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
391 self.capabilities_proxy
392 .capability_associate_handle(
393 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
394 "failed to duplicate handle, please only use handles with the duplicate right",
395 ),
396 other_handle,
397 )
398 .await
399 .expect("failed to use fuchsia.component.runtime.Capabilities")
400 .expect("failed to clone onto handle, does it have sufficient rights?");
401 }
402
403 pub async fn get_value(&self) -> DataValue {
404 self.capabilities_proxy
405 .data_get(self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
406 "failed to duplicate handle, please only use handles with the duplicate right",
407 ))
408 .await
409 .expect("failed to use fuchsia.component.runtime.Capabilities")
410 .expect("failed to get data value")
411 .try_into()
412 .expect("we were sent an invalid data value")
413 }
414 }
415
416 impl Clone for Data {
417 fn clone(&self) -> Self {
418 Self {
419 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
420 "failed to duplicate handle, please only use handles with the duplicate right",
421 ),
422 capabilities_proxy: self.capabilities_proxy.clone(),
423 }
424 }
425 }
426
427 #[derive(Debug)]
429 pub struct Connector {
430 pub handle: zx::EventPair,
432
433 pub capabilities_proxy: fruntime::CapabilitiesProxy,
436 }
437
438 impl Connector {
439 pub async fn new() -> (Self, ConnectorReceiver) {
442 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
443 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
444 Self::new_with_proxy(proxy).await
445 }
446
447 pub async fn new_with_proxy(
449 capabilities_proxy: fruntime::CapabilitiesProxy,
450 ) -> (Self, ConnectorReceiver) {
451 let (handle, handle_other_end) = zx::EventPair::create();
452 let (receiver_client_end, stream) = create_request_stream::<fruntime::ReceiverMarker>();
453 capabilities_proxy
454 .connector_create(handle_other_end, receiver_client_end)
455 .await
456 .expect("failed to use fuchsia.component.runtime.Capabilities")
457 .expect(
458 "this should be impossible, we passed a valid handle with the correct rights",
459 );
460 let connector = Self { handle, capabilities_proxy };
461 let receiver = ConnectorReceiver { stream };
462 (connector, receiver)
463 }
464
465 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
468 self.capabilities_proxy
469 .capability_associate_handle(
470 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
471 "failed to duplicate handle, please only use handles with the duplicate right",
472 ),
473 other_handle,
474 )
475 .await
476 .expect("failed to use fuchsia.component.runtime.Capabilities")
477 .expect("failed to clone onto handle, does it have sufficient rights?");
478 }
479
480 pub async fn connect(
481 &self,
482 channel: zx::Channel,
483 ) -> Result<(), fruntime::CapabilitiesError> {
484 self.capabilities_proxy
485 .connector_open(
486 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
487 "failed to duplicate handle, please only use handles with the duplicate right",
488 ),
489 channel,
490 )
491 .await
492 .expect("failed to use fuchsia.component.runtime.Capabilities")
493 }
494 }
495
496 impl Clone for Connector {
497 fn clone(&self) -> Self {
498 Self {
499 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
500 "failed to duplicate handle, please only use handles with the duplicate right",
501 ),
502 capabilities_proxy: self.capabilities_proxy.clone(),
503 }
504 }
505 }
506
507 #[derive(Debug)]
510 pub struct DirConnector {
511 pub handle: zx::EventPair,
513
514 pub capabilities_proxy: fruntime::CapabilitiesProxy,
517 }
518
519 impl DirConnector {
520 pub async fn new() -> (Self, DirConnectorReceiver) {
523 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
524 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
525 Self::new_with_proxy(proxy).await
526 }
527
528 pub async fn new_with_proxy(
530 capabilities_proxy: fruntime::CapabilitiesProxy,
531 ) -> (Self, DirConnectorReceiver) {
532 let (handle, handle_other_end) = zx::EventPair::create();
533 let (receiver_client_end, stream) =
534 create_request_stream::<fruntime::DirReceiverMarker>();
535 capabilities_proxy
536 .dir_connector_create(handle_other_end, receiver_client_end)
537 .await
538 .expect("failed to use fuchsia.component.runtime.Capabilities")
539 .expect(
540 "this should be impossible, we passed a valid handle with the correct rights",
541 );
542 let connector = Self { handle, capabilities_proxy };
543 let receiver = DirConnectorReceiver { stream };
544 (connector, receiver)
545 }
546
547 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
550 self.capabilities_proxy
551 .capability_associate_handle(
552 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
553 "failed to duplicate handle, please only use handles with the duplicate right",
554 ),
555 other_handle,
556 )
557 .await
558 .expect("failed to use fuchsia.component.runtime.Capabilities")
559 .expect("failed to clone onto handle, does it have sufficient rights?");
560 }
561
562 pub async fn connect(
563 &self,
564 server_end: ServerEnd<fio::DirectoryMarker>,
565 flags: Option<fio::Flags>,
566 path: Option<String>,
567 ) -> Result<(), fruntime::CapabilitiesError> {
568 self.capabilities_proxy
569 .dir_connector_open(fruntime::CapabilitiesDirConnectorOpenRequest {
570 dir_connector: Some(self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
571 "failed to duplicate handle, please only use handles with the duplicate right",
572 )),
573 channel: Some(server_end),
574 flags,
575 path,
576 ..Default::default()
577 })
578 .await
579 .expect("failed to use fuchsia.component.runtime.Capabilities")
580 }
581 }
582
583 impl Clone for DirConnector {
584 fn clone(&self) -> Self {
585 Self {
586 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
587 "failed to duplicate handle, please only use handles with the duplicate right",
588 ),
589 capabilities_proxy: self.capabilities_proxy.clone(),
590 }
591 }
592 }
593
594 #[derive(Debug)]
596 pub struct Dictionary {
597 pub handle: zx::EventPair,
599
600 pub capabilities_proxy: fruntime::CapabilitiesProxy,
603 }
604
605 impl Dictionary {
606 pub async fn new() -> Self {
609 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
610 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
611 Self::new_with_proxy(proxy).await
612 }
613
614 pub async fn new_with_proxy(capabilities_proxy: fruntime::CapabilitiesProxy) -> Self {
616 let (handle, handle_other_end) = zx::EventPair::create();
617 capabilities_proxy
618 .dictionary_create(handle_other_end)
619 .await
620 .expect("failed to use fuchsia.component.runtime.Capabilities")
621 .expect(
622 "this should be impossible, we passed a valid handle with the correct rights",
623 );
624 Self { handle, capabilities_proxy }
625 }
626
627 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
630 self.capabilities_proxy
631 .capability_associate_handle(
632 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
633 "failed to duplicate handle, please only use handles with the duplicate right",
634 ),
635 other_handle,
636 )
637 .await
638 .expect("failed to use fuchsia.component.runtime.Capabilities")
639 .expect("failed to clone onto handle, does it have sufficient rights?");
640 }
641
642 pub async fn insert(&self, key: &str, value: impl Into<Capability>) {
643 let capability: Capability = value.into();
644 let dictionary = self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
645 "failed to duplicate handle, please only use handles with the duplicate right",
646 );
647 let handle =
648 capability.as_event_pair().duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
649 "failed to duplicate handle, please only use handles with the duplicate right",
650 );
651 self.capabilities_proxy
652 .dictionary_insert(dictionary, key, handle)
653 .await
654 .expect("failed to use fuchsia.component.runtime.Capabilities")
655 .expect("failed to insert into dictionary")
656 }
657
658 pub async fn get(&self, key: &str) -> Option<Capability> {
659 let (handle, handle_other_end) = zx::EventPair::create();
660 let res = self
661 .capabilities_proxy
662 .dictionary_get(
663 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
664 "failed to duplicate handle, please only use handles with the duplicate right",
665 ),
666 key,
667 handle_other_end,
668 )
669 .await
670 .expect("failed to use fuchsia.component.runtime.Capabilities");
671 match res {
672 Ok(type_) => Some(Capability::from_raw_with_proxy(
673 self.capabilities_proxy.clone(),
674 handle,
675 type_,
676 )),
677 Err(fruntime::CapabilitiesError::NoSuchCapability) => None,
678 Err(other_error) => panic!(
679 "this arm should be impossible, we passed a valid handle with the correct rights: {other_error:?}"
680 ),
681 }
682 }
683
684 pub async fn remove(&self, key: &str) -> Option<Capability> {
685 let (handle, handle_other_end) = zx::EventPair::create();
686 let res = self
687 .capabilities_proxy
688 .dictionary_remove(fruntime::CapabilitiesDictionaryRemoveRequest {
689 dictionary: Some(self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
690 "failed to duplicate handle, please only use handles with the duplicate right",
691 )),
692 key: Some(key.to_string()),
693 value: Some(handle_other_end),
694 ..Default::default()
695 })
696 .await
697 .expect("failed to use fuchsia.component.runtime.Capabilities");
698 match res {
699 Ok(type_) => Some(Capability::from_raw_with_proxy(
700 self.capabilities_proxy.clone(),
701 handle,
702 type_,
703 )),
704 Err(fruntime::CapabilitiesError::NoSuchCapability) => None,
705 Err(other_error) => panic!(
706 "this arm should be impossible, we passed a valid handle with the correct rights: {other_error:?}"
707 ),
708 }
709 }
710
711 pub async fn keys(&self) -> DictionaryKeysStream {
712 let (key_iterator_proxy, key_iterator_server_end) =
713 create_proxy::<fruntime::DictionaryKeyIteratorMarker>();
714 self.capabilities_proxy
715 .dictionary_iterate_keys(
716 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
717 "failed to duplicate handle, please only use handles with the duplicate right",
718 ),
719 key_iterator_server_end,
720 )
721 .await
722 .expect("failed to use fuchsia.component.runtime.Capabilities")
723 .expect("failed to iterate keys");
724 DictionaryKeysStream { key_iterator_proxy, key_cache: vec![], more_keys_fut: None }
725 }
726 }
727
728 impl Clone for Dictionary {
729 fn clone(&self) -> Self {
730 Self {
731 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
732 "failed to duplicate handle, please only use handles with the duplicate right",
733 ),
734 capabilities_proxy: self.capabilities_proxy.clone(),
735 }
736 }
737 }
738
739 pub struct DictionaryKeysStream {
740 key_iterator_proxy: fruntime::DictionaryKeyIteratorProxy,
741 key_cache: Vec<String>,
742 more_keys_fut: Option<
743 fidl::client::QueryResponseFut<
744 Vec<String>,
745 fidl::encoding::DefaultFuchsiaResourceDialect,
746 >,
747 >,
748 }
749
750 impl Stream for DictionaryKeysStream {
751 type Item = String;
752
753 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
754 if let Some(key) = self.key_cache.pop() {
755 return Poll::Ready(Some(key));
756 }
757 if self.more_keys_fut.is_none() {
758 self.more_keys_fut = Some(self.key_iterator_proxy.get_next());
759 }
760
761 let fut = self.more_keys_fut.as_mut().expect("we just checked if this was None");
762 let fut = pin!(fut);
763 match fut.poll(cx) {
764 Poll::Ready(Ok(mut keys)) if !keys.is_empty() => {
765 self.key_cache.append(&mut keys);
766 self.key_cache.reverse();
767 self.more_keys_fut = None;
768 Poll::Ready(self.key_cache.pop())
769 }
770 Poll::Pending => Poll::Pending,
771 _ => Poll::Ready(None),
772 }
773 }
774 }
775
776 #[derive(Debug)]
780 pub struct InstanceToken {
781 pub handle: zx::EventPair,
783 }
784
785 impl InstanceToken {
786 pub async fn new() -> Self {
791 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
792 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
793 Self::new_with_proxy(proxy).await
794 }
795
796 pub async fn new_with_proxy(capabilities_proxy: fruntime::CapabilitiesProxy) -> Self {
798 let (handle, handle_other_end) = zx::EventPair::create();
799 capabilities_proxy
800 .instance_token_create(handle_other_end)
801 .await
802 .expect("failed to use fuchsia.component.runtime.Capabilities")
803 .expect(
804 "this should be impossible, we passed a valid handle with the correct rights",
805 );
806 Self { handle }
807 }
808 }
809
810 impl Clone for InstanceToken {
811 fn clone(&self) -> Self {
812 Self {
813 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
814 "failed to duplicate handle, please only use handles with the duplicate right",
815 ),
816 }
817 }
818 }
819
820 #[derive(Debug)]
825 pub struct ConnectorRouter {
826 pub handle: zx::EventPair,
828
829 pub capabilities_proxy: fruntime::CapabilitiesProxy,
832 }
833
834 impl ConnectorRouter {
835 pub async fn new() -> (Self, ConnectorRouterReceiver) {
838 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
839 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
840 Self::new_with_proxy(proxy).await
841 }
842
843 pub async fn new_with_proxy(
845 capabilities_proxy: fruntime::CapabilitiesProxy,
846 ) -> (Self, ConnectorRouterReceiver) {
847 let (handle, handle_other_end) = zx::EventPair::create();
848 let (client_end, stream) = create_request_stream::<fruntime::ConnectorRouterMarker>();
849 capabilities_proxy
850 .connector_router_create(handle_other_end, client_end)
851 .await
852 .expect("failed to use fuchsia.component.runtime.Capabilities")
853 .expect(
854 "this should be impossible, we passed a valid handle with the correct rights",
855 );
856 let connector = Self { handle, capabilities_proxy };
857 let receiver = ConnectorRouterReceiver { stream };
858 (connector, receiver)
859 }
860
861 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
864 self.capabilities_proxy
865 .capability_associate_handle(
866 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
867 "failed to duplicate handle, please only use handles with the duplicate right",
868 ),
869 other_handle,
870 )
871 .await
872 .expect("failed to use fuchsia.component.runtime.Capabilities")
873 .expect("failed to clone onto handle, does it have sufficient rights?");
874 }
875
876 pub async fn route(
877 &self,
878 request: fruntime::RouteRequest,
879 instance_token: &InstanceToken,
880 ) -> Result<Option<Connector>, zx::Status> {
881 let (connector, connector_other_end) = zx::EventPair::create();
882 let res = self
883 .capabilities_proxy
884 .connector_router_route(
885 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
886 "failed to duplicate handle, please only use handles with the duplicate right",
887 ),
888 request,
889 instance_token.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
890 "failed to duplicate handle, please only use handles with the duplicate right",
891 ),
892 connector_other_end,
893 )
894 .await
895 .expect("failed to use fuchsia.component.runtime.Capabilities");
896 match res.map_err(|s| zx::Status::from_raw(s))? {
897 fruntime::RouterResponse::Success => Ok(Some(Connector {
898 handle: connector,
899 capabilities_proxy: self.capabilities_proxy.clone(),
900 })),
901 fruntime::RouterResponse::Unavailable => Ok(None),
902 _ => Err(zx::Status::INTERNAL),
903 }
904 }
905 }
906
907 impl Clone for ConnectorRouter {
908 fn clone(&self) -> Self {
909 Self {
910 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
911 "failed to duplicate handle, please only use handles with the duplicate right",
912 ),
913 capabilities_proxy: self.capabilities_proxy.clone(),
914 }
915 }
916 }
917
918 pub struct ConnectorRouterReceiver {
920 pub stream: fruntime::ConnectorRouterRequestStream,
921 }
922
923 impl Stream for ConnectorRouterReceiver {
924 type Item = (
925 fruntime::RouteRequest,
926 InstanceToken,
927 zx::EventPair,
928 fruntime::ConnectorRouterRouteResponder,
929 );
930
931 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
932 let pinned_stream = pin!(&mut self.stream);
933 match pinned_stream.poll_next(cx) {
934 Poll::Pending => Poll::Pending,
935 Poll::Ready(Some(Ok(fruntime::ConnectorRouterRequest::Route {
936 request,
937 instance_token,
938 handle,
939 responder,
940 }))) => {
941 let instance_token = InstanceToken { handle: instance_token };
942 Poll::Ready(Some((request, instance_token, handle, responder)))
943 }
944 _ => Poll::Ready(None),
945 }
946 }
947 }
948
949 #[derive(Debug)]
954 pub struct DirConnectorRouter {
955 pub handle: zx::EventPair,
957
958 pub capabilities_proxy: fruntime::CapabilitiesProxy,
961 }
962
963 impl DirConnectorRouter {
964 pub async fn new() -> (Self, DirConnectorRouterReceiver) {
967 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
968 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
969 Self::new_with_proxy(proxy).await
970 }
971
972 pub async fn new_with_proxy(
974 capabilities_proxy: fruntime::CapabilitiesProxy,
975 ) -> (Self, DirConnectorRouterReceiver) {
976 let (handle, handle_other_end) = zx::EventPair::create();
977 let (client_end, stream) =
978 create_request_stream::<fruntime::DirConnectorRouterMarker>();
979 capabilities_proxy
980 .dir_connector_router_create(handle_other_end, client_end)
981 .await
982 .expect("failed to use fuchsia.component.runtime.Capabilities")
983 .expect(
984 "this should be impossible, we passed a valid handle with the correct rights",
985 );
986 let connector = Self { handle, capabilities_proxy };
987 let receiver = DirConnectorRouterReceiver { stream };
988 (connector, receiver)
989 }
990
991 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
994 self.capabilities_proxy
995 .capability_associate_handle(
996 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
997 "failed to duplicate handle, please only use handles with the duplicate right",
998 ),
999 other_handle,
1000 )
1001 .await
1002 .expect("failed to use fuchsia.component.runtime.Capabilities")
1003 .expect("failed to clone onto handle, does it have sufficient rights?");
1004 }
1005
1006 pub async fn route(
1007 &self,
1008 request: fruntime::RouteRequest,
1009 instance_token: &InstanceToken,
1010 ) -> Result<Option<DirConnector>, zx::Status> {
1011 let (connector, connector_other_end) = zx::EventPair::create();
1012 let res = self
1013 .capabilities_proxy
1014 .dir_connector_router_route(
1015 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1016 "failed to duplicate handle, please only use handles with the duplicate right",
1017 ),
1018 request,
1019 instance_token.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1020 "failed to duplicate handle, please only use handles with the duplicate right",
1021 ),
1022 connector_other_end,
1023 )
1024 .await
1025 .expect("failed to use fuchsia.component.runtime.Capabilities");
1026 match res.map_err(|s| zx::Status::from_raw(s))? {
1027 fruntime::RouterResponse::Success => Ok(Some(DirConnector {
1028 handle: connector,
1029 capabilities_proxy: self.capabilities_proxy.clone(),
1030 })),
1031 fruntime::RouterResponse::Unavailable => Ok(None),
1032 _ => Err(zx::Status::INTERNAL),
1033 }
1034 }
1035 }
1036
1037 impl Clone for DirConnectorRouter {
1038 fn clone(&self) -> Self {
1039 Self {
1040 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1041 "failed to duplicate handle, please only use handles with the duplicate right",
1042 ),
1043 capabilities_proxy: self.capabilities_proxy.clone(),
1044 }
1045 }
1046 }
1047
1048 pub struct DirConnectorRouterReceiver {
1050 pub stream: fruntime::DirConnectorRouterRequestStream,
1051 }
1052
1053 impl Stream for DirConnectorRouterReceiver {
1054 type Item = (
1055 fruntime::RouteRequest,
1056 InstanceToken,
1057 zx::EventPair,
1058 fruntime::DirConnectorRouterRouteResponder,
1059 );
1060
1061 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
1062 let pinned_stream = pin!(&mut self.stream);
1063 match pinned_stream.poll_next(cx) {
1064 Poll::Pending => Poll::Pending,
1065 Poll::Ready(Some(Ok(fruntime::DirConnectorRouterRequest::Route {
1066 request,
1067 instance_token,
1068 handle,
1069 responder,
1070 }))) => {
1071 let instance_token = InstanceToken { handle: instance_token };
1072 Poll::Ready(Some((request, instance_token, handle, responder)))
1073 }
1074 _ => Poll::Ready(None),
1075 }
1076 }
1077 }
1078
1079 #[derive(Debug)]
1084 pub struct DictionaryRouter {
1085 pub handle: zx::EventPair,
1087
1088 pub capabilities_proxy: fruntime::CapabilitiesProxy,
1091 }
1092
1093 impl DictionaryRouter {
1094 pub async fn new() -> (Self, DictionaryRouterReceiver) {
1097 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
1098 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
1099 Self::new_with_proxy(proxy).await
1100 }
1101
1102 pub async fn new_with_proxy(
1104 capabilities_proxy: fruntime::CapabilitiesProxy,
1105 ) -> (Self, DictionaryRouterReceiver) {
1106 let (handle, handle_other_end) = zx::EventPair::create();
1107 let (client_end, stream) = create_request_stream::<fruntime::DictionaryRouterMarker>();
1108 capabilities_proxy
1109 .dictionary_router_create(handle_other_end, client_end)
1110 .await
1111 .expect("failed to use fuchsia.component.runtime.Capabilities")
1112 .expect(
1113 "this should be impossible, we passed a valid handle with the correct rights",
1114 );
1115 let connector = Self { handle, capabilities_proxy };
1116 let receiver = DictionaryRouterReceiver { stream };
1117 (connector, receiver)
1118 }
1119
1120 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
1123 self.capabilities_proxy
1124 .capability_associate_handle(
1125 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1126 "failed to duplicate handle, please only use handles with the duplicate right",
1127 ),
1128 other_handle,
1129 )
1130 .await
1131 .expect("failed to use fuchsia.component.runtime.Capabilities")
1132 .expect("failed to clone onto handle, does it have sufficient rights?");
1133 }
1134
1135 pub async fn route(
1136 &self,
1137 request: fruntime::RouteRequest,
1138 instance_token: &InstanceToken,
1139 ) -> Result<Option<Dictionary>, zx::Status> {
1140 let (connector, connector_other_end) = zx::EventPair::create();
1141 let res = self
1142 .capabilities_proxy
1143 .dictionary_router_route(
1144 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1145 "failed to duplicate handle, please only use handles with the duplicate right",
1146 ),
1147 request,
1148 instance_token.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1149 "failed to duplicate handle, please only use handles with the duplicate right",
1150 ),
1151 connector_other_end,
1152 )
1153 .await
1154 .expect("failed to use fuchsia.component.runtime.Capabilities");
1155 match res.map_err(|s| zx::Status::from_raw(s))? {
1156 fruntime::RouterResponse::Success => Ok(Some(Dictionary {
1157 handle: connector,
1158 capabilities_proxy: self.capabilities_proxy.clone(),
1159 })),
1160 fruntime::RouterResponse::Unavailable => Ok(None),
1161 _ => Err(zx::Status::INTERNAL),
1162 }
1163 }
1164 }
1165
1166 impl Clone for DictionaryRouter {
1167 fn clone(&self) -> Self {
1168 Self {
1169 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1170 "failed to duplicate handle, please only use handles with the duplicate right",
1171 ),
1172 capabilities_proxy: self.capabilities_proxy.clone(),
1173 }
1174 }
1175 }
1176
1177 pub struct DictionaryRouterReceiver {
1179 pub stream: fruntime::DictionaryRouterRequestStream,
1180 }
1181
1182 impl Stream for DictionaryRouterReceiver {
1183 type Item = (
1184 fruntime::RouteRequest,
1185 InstanceToken,
1186 zx::EventPair,
1187 fruntime::DictionaryRouterRouteResponder,
1188 );
1189
1190 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
1191 let pinned_stream = pin!(&mut self.stream);
1192 match pinned_stream.poll_next(cx) {
1193 Poll::Pending => Poll::Pending,
1194 Poll::Ready(Some(Ok(fruntime::DictionaryRouterRequest::Route {
1195 request,
1196 instance_token,
1197 handle,
1198 responder,
1199 }))) => {
1200 let instance_token = InstanceToken { handle: instance_token };
1201 Poll::Ready(Some((request, instance_token, handle, responder)))
1202 }
1203 _ => Poll::Ready(None),
1204 }
1205 }
1206 }
1207
1208 #[derive(Debug)]
1213 pub struct DataRouter {
1214 pub handle: zx::EventPair,
1216
1217 pub capabilities_proxy: fruntime::CapabilitiesProxy,
1220 }
1221
1222 impl DataRouter {
1223 pub async fn new() -> (Self, DataRouterReceiver) {
1226 let proxy = connect_to_protocol::<fruntime::CapabilitiesMarker>()
1227 .expect("failed to connect to fuchsia.component.runtime.Capabilities");
1228 Self::new_with_proxy(proxy).await
1229 }
1230
1231 pub async fn new_with_proxy(
1233 capabilities_proxy: fruntime::CapabilitiesProxy,
1234 ) -> (Self, DataRouterReceiver) {
1235 let (handle, handle_other_end) = zx::EventPair::create();
1236 let (client_end, stream) = create_request_stream::<fruntime::DataRouterMarker>();
1237 capabilities_proxy
1238 .data_router_create(handle_other_end, client_end)
1239 .await
1240 .expect("failed to use fuchsia.component.runtime.Capabilities")
1241 .expect(
1242 "this should be impossible, we passed a valid handle with the correct rights",
1243 );
1244 let connector = Self { handle, capabilities_proxy };
1245 let receiver = DataRouterReceiver { stream };
1246 (connector, receiver)
1247 }
1248
1249 pub async fn associate_with_handle(&self, other_handle: zx::EventPair) {
1252 self.capabilities_proxy
1253 .capability_associate_handle(
1254 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1255 "failed to duplicate handle, please only use handles with the duplicate right",
1256 ),
1257 other_handle,
1258 )
1259 .await
1260 .expect("failed to use fuchsia.component.runtime.Capabilities")
1261 .expect("failed to clone onto handle, does it have sufficient rights?");
1262 }
1263
1264 pub async fn route(
1265 &self,
1266 request: fruntime::RouteRequest,
1267 instance_token: &InstanceToken,
1268 ) -> Result<Option<Data>, zx::Status> {
1269 let (connector, connector_other_end) = zx::EventPair::create();
1270 let res = self
1271 .capabilities_proxy
1272 .data_router_route(
1273 self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1274 "failed to duplicate handle, please only use handles with the duplicate right",
1275 ),
1276 request,
1277 instance_token.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1278 "failed to duplicate handle, please only use handles with the duplicate right",
1279 ),
1280 connector_other_end,
1281 )
1282 .await
1283 .expect("failed to use fuchsia.component.runtime.Capabilities");
1284 match res.map_err(|s| zx::Status::from_raw(s))? {
1285 fruntime::RouterResponse::Success => Ok(Some(Data {
1286 handle: connector,
1287 capabilities_proxy: self.capabilities_proxy.clone(),
1288 })),
1289 fruntime::RouterResponse::Unavailable => Ok(None),
1290 _ => Err(zx::Status::INTERNAL),
1291 }
1292 }
1293 }
1294
1295 impl Clone for DataRouter {
1296 fn clone(&self) -> Self {
1297 Self {
1298 handle: self.handle.duplicate_handle(zx::Rights::SAME_RIGHTS).expect(
1299 "failed to duplicate handle, please only use handles with the duplicate right",
1300 ),
1301 capabilities_proxy: self.capabilities_proxy.clone(),
1302 }
1303 }
1304 }
1305
1306 pub struct DataRouterReceiver {
1308 pub stream: fruntime::DataRouterRequestStream,
1309 }
1310
1311 impl Stream for DataRouterReceiver {
1312 type Item = (
1313 fruntime::RouteRequest,
1314 InstanceToken,
1315 zx::EventPair,
1316 fruntime::DataRouterRouteResponder,
1317 );
1318
1319 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
1320 let pinned_stream = pin!(&mut self.stream);
1321 match pinned_stream.poll_next(cx) {
1322 Poll::Pending => Poll::Pending,
1323 Poll::Ready(Some(Ok(fruntime::DataRouterRequest::Route {
1324 request,
1325 instance_token,
1326 handle,
1327 responder,
1328 }))) => {
1329 let instance_token = InstanceToken { handle: instance_token };
1330 Poll::Ready(Some((request, instance_token, handle, responder)))
1331 }
1332 _ => Poll::Ready(None),
1333 }
1334 }
1335 }
1336
1337 #[cfg(test)]
1338 mod tests {
1339 use super::*;
1340 use assert_matches::assert_matches;
1341 use futures::StreamExt;
1342 use std::collections::HashSet;
1343 use zx::AsHandleRef;
1344
1345 #[fuchsia::test]
1346 async fn connector_test() {
1347 let (connector, mut receiver) = Connector::new().await;
1348 let (c1, c2) = zx::Channel::create();
1349 connector.connect(c1).await.unwrap();
1350 let c1 = receiver.next().await.unwrap();
1351 assert_eq!(c1.basic_info().unwrap().koid, c2.basic_info().unwrap().related_koid);
1352 }
1353
1354 #[fuchsia::test]
1355 async fn dir_connector_test() {
1356 let (dir_connector, mut dir_receiver) = DirConnector::new().await;
1357 let (client_end, server_end) =
1358 fidl::endpoints::create_endpoints::<fio::DirectoryMarker>();
1359 dir_connector
1360 .connect(server_end, Some(fio::PERM_WRITABLE), Some("foo/bar".to_string()))
1361 .await
1362 .unwrap();
1363 let dir_request = dir_receiver.next().await.unwrap();
1364 assert_eq!(
1365 client_end.basic_info().unwrap().koid,
1366 dir_request.channel.basic_info().unwrap().related_koid
1367 );
1368 assert_eq!("foo/bar", dir_request.path);
1369 assert_eq!(fio::PERM_WRITABLE, dir_request.flags);
1370 }
1371
1372 #[fuchsia::test]
1373 async fn dictionary_test() {
1374 let dictionary = Dictionary::new().await;
1375 assert!(dictionary.get("foo").await.is_none());
1376 dictionary.insert("foo", Dictionary::new().await).await;
1377 assert_matches!(dictionary.get("foo").await, Some(Capability::Dictionary(_)));
1378 let mut keys_stream = dictionary.keys().await;
1379 assert_eq!(Some("foo".to_string()), keys_stream.next().await);
1380 assert_eq!(None, keys_stream.next().await);
1381
1382 assert_matches!(dictionary.remove("foo").await, Some(Capability::Dictionary(_)));
1383 assert_matches!(dictionary.remove("foo").await, None);
1384 assert!(dictionary.get("foo").await.is_none());
1385 }
1386
1387 #[fuchsia::test]
1388 async fn dictionary_key_iterator_many_keys_test() {
1389 let dictionary = Dictionary::new().await;
1390
1391 let mut keys = HashSet::new();
1393 for i in 0..zx::sys::ZX_CHANNEL_MAX_MSG_BYTES / 50 {
1394 keys.insert(format!("{:0100}", i));
1395 }
1396 for key in keys.iter() {
1397 dictionary.insert(key.as_str(), Dictionary::new().await).await;
1398 }
1399
1400 let mut keys_stream = dictionary.keys().await;
1401 let mut returned_keys = HashSet::new();
1402 while let Some(key) = keys_stream.next().await {
1403 returned_keys.insert(key);
1404 }
1405 assert_eq!(keys, returned_keys);
1406 }
1407
1408 #[fuchsia::test]
1409 async fn all_capabilities_into_and_out_of_a_dictionary_test() {
1410 let dictionary = Dictionary::new().await;
1411 let (connector, _receiver) = Connector::new().await;
1412 dictionary.insert("connector", connector).await;
1413 let (dir_connector, _dir_receiver) = DirConnector::new().await;
1414 dictionary.insert("dir_connector", dir_connector).await;
1415 dictionary.insert("dictionary", Dictionary::new().await).await;
1416 dictionary.insert("data", Data::new(DataValue::Int64(1)).await).await;
1417 let (connector_router, _connector_router_receiver) = ConnectorRouter::new().await;
1418 dictionary.insert("connector_router", connector_router).await;
1419 let (dir_connector_router, _dir_connector_router_receiver) =
1420 DirConnectorRouter::new().await;
1421 dictionary.insert("dir_connector_router", dir_connector_router).await;
1422 let (dictionary_router, _dictionary_router_receiver) = DictionaryRouter::new().await;
1423 dictionary.insert("dictionary_router", dictionary_router).await;
1424 let (data_router, _data_router_receiver) = DataRouter::new().await;
1425 dictionary.insert("data_router", data_router).await;
1426 dictionary.insert("instance_token", InstanceToken::new().await).await;
1427
1428 assert_matches!(dictionary.get("connector").await, Some(Capability::Connector(_)));
1429 assert_matches!(
1430 dictionary.get("dir_connector").await,
1431 Some(Capability::DirConnector(_))
1432 );
1433 assert_matches!(dictionary.get("dictionary").await, Some(Capability::Dictionary(_)));
1434 assert_matches!(dictionary.get("data").await, Some(Capability::Data(_)));
1435 assert_matches!(
1436 dictionary.get("connector_router").await,
1437 Some(Capability::ConnectorRouter(_))
1438 );
1439 assert_matches!(
1440 dictionary.get("dir_connector_router").await,
1441 Some(Capability::DirConnectorRouter(_))
1442 );
1443 assert_matches!(
1444 dictionary.get("dictionary_router").await,
1445 Some(Capability::DictionaryRouter(_))
1446 );
1447 assert_matches!(dictionary.get("data_router").await, Some(Capability::DataRouter(_)));
1448 assert_matches!(
1449 dictionary.get("instance_token").await,
1450 Some(Capability::InstanceToken(_))
1451 );
1452 }
1453
1454 #[fuchsia::test]
1455 async fn data_test() {
1456 let data = Data::new(DataValue::Uint64(100)).await;
1457 assert_eq!(DataValue::Uint64(100), data.get_value().await);
1458 }
1459
1460 #[fuchsia::test]
1461 async fn connector_router_test() {
1462 let (connector_router, mut connector_router_receiver) = ConnectorRouter::new().await;
1463
1464 let result_fut = fuchsia_async::Task::spawn(async move {
1465 let instance_token = InstanceToken::new().await;
1466 connector_router.route(fruntime::RouteRequest::default(), &instance_token).await
1467 });
1468
1469 let (_route_request, _instance_token, handle, responder) =
1470 connector_router_receiver.next().await.unwrap();
1471 let (connector, mut receiver) = Connector::new().await;
1472 connector.associate_with_handle(handle).await;
1473 responder.send(Ok(fruntime::RouterResponse::Success)).unwrap();
1474
1475 let connector = match result_fut.await {
1476 Ok(Some(connector)) => connector,
1477 other_value => panic!("unexpected route result: {other_value:?}"),
1478 };
1479
1480 let (c1, c2) = zx::Channel::create();
1481 connector.connect(c1).await.unwrap();
1482 let c1 = receiver.next().await.unwrap();
1483 assert_eq!(c1.basic_info().unwrap().koid, c2.basic_info().unwrap().related_koid);
1484 }
1485
1486 #[fuchsia::test]
1487 async fn dir_connector_router_test() {
1488 let (dir_connector_router, mut dir_connector_router_receiver) =
1489 DirConnectorRouter::new().await;
1490
1491 let result_fut = fuchsia_async::Task::spawn(async move {
1492 let instance_token = InstanceToken::new().await;
1493 dir_connector_router.route(fruntime::RouteRequest::default(), &instance_token).await
1494 });
1495
1496 let (_route_request, _instance_token, handle, responder) =
1497 dir_connector_router_receiver.next().await.unwrap();
1498 let (dir_connector, mut dir_receiver) = DirConnector::new().await;
1499 dir_connector.associate_with_handle(handle).await;
1500 responder.send(Ok(fruntime::RouterResponse::Success)).unwrap();
1501
1502 let dir_connector = match result_fut.await {
1503 Ok(Some(dir_connector)) => dir_connector,
1504 other_value => panic!("unexpected route result: {other_value:?}"),
1505 };
1506
1507 let (client_end, server_end) =
1508 fidl::endpoints::create_endpoints::<fio::DirectoryMarker>();
1509 dir_connector
1510 .connect(server_end, Some(fio::PERM_WRITABLE), Some("foo/bar".to_string()))
1511 .await
1512 .unwrap();
1513 let dir_request = dir_receiver.next().await.unwrap();
1514 assert_eq!(
1515 client_end.basic_info().unwrap().koid,
1516 dir_request.channel.basic_info().unwrap().related_koid
1517 );
1518 assert_eq!("foo/bar", dir_request.path);
1519 assert_eq!(fio::PERM_WRITABLE, dir_request.flags);
1520 }
1521
1522 #[fuchsia::test]
1523 async fn dictionary_router_test() {
1524 let (dictionary_router, mut dictionary_router_receiver) = DictionaryRouter::new().await;
1525
1526 let result_fut = fuchsia_async::Task::spawn(async move {
1527 let instance_token = InstanceToken::new().await;
1528 dictionary_router.route(fruntime::RouteRequest::default(), &instance_token).await
1529 });
1530
1531 let (_route_request, _instance_token, handle, responder) =
1532 dictionary_router_receiver.next().await.unwrap();
1533 let dictionary = Dictionary::new().await;
1534 dictionary.insert("foo", Data::new(DataValue::String("bar".to_string())).await).await;
1535 dictionary.associate_with_handle(handle).await;
1536 responder.send(Ok(fruntime::RouterResponse::Success)).unwrap();
1537
1538 let dictionary = match result_fut.await {
1539 Ok(Some(dictionary)) => dictionary,
1540 other_value => panic!("unexpected route result: {other_value:?}"),
1541 };
1542
1543 let data = match dictionary.get("foo").await {
1544 Some(Capability::Data(data)) => data,
1545 other_value => panic!("unexpected dictionary contents: {other_value:?}"),
1546 };
1547 assert_eq!(data.get_value().await, DataValue::String("bar".to_string()));
1548 }
1549 }
1550}