fuchsia_scenic/
view_ref_pair.rs

1// Copyright 2020 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 anyhow::Error;
6use fidl_fuchsia_ui_views::{ViewRef, ViewRefControl};
7use zx::{AsHandleRef, EventPair, HandleBased, Rights, Status};
8
9pub struct ViewRefPair {
10    pub control_ref: ViewRefControl,
11    pub view_ref: ViewRef,
12}
13
14impl ViewRefPair {
15    pub fn new() -> Result<ViewRefPair, Error> {
16        let (raw_control_ref, raw_view_ref) = EventPair::create();
17
18        // Remove duplication from the control ref. This is the same
19        // as `ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE)`
20        let new_rights = (Rights::BASIC | Rights::SIGNAL | Rights::SIGNAL_PEER) - Rights::DUPLICATE;
21        let control_ref = raw_control_ref.into_handle().replace(new_rights)?;
22
23        // Remove signaling from the view_ref
24        let view_ref = raw_view_ref.into_handle().replace(Rights::BASIC)?;
25
26        Ok(ViewRefPair {
27            control_ref: ViewRefControl { reference: control_ref.into() },
28            view_ref: ViewRef { reference: view_ref.into() },
29        })
30    }
31}
32
33impl From<ViewRefPair> for fidl_fuchsia_ui_views::ViewIdentityOnCreation {
34    fn from(item: ViewRefPair) -> Self {
35        fidl_fuchsia_ui_views::ViewIdentityOnCreation {
36            view_ref: item.view_ref,
37            view_ref_control: item.control_ref,
38        }
39    }
40}
41
42/// Given a ViewRef, returns a new version which has been duplicated.
43pub fn duplicate_view_ref(view_ref: &ViewRef) -> Result<ViewRef, Status> {
44    let handle = view_ref.reference.as_handle_ref().duplicate(Rights::SAME_RIGHTS)?;
45    Ok(ViewRef { reference: handle.into() })
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    macro_rules! assert_not_contains_rights {
53        ($handle:expr, $test_rights:expr) => {
54            let basic_info = $handle.reference.as_handle_ref().basic_info().unwrap();
55            assert_eq!(basic_info.rights & $test_rights, Rights::NONE);
56        };
57    }
58
59    macro_rules! assert_contains_rights {
60        ($handle:expr, $test_rights:expr) => {
61            let basic_info = $handle.reference.as_handle_ref().basic_info().unwrap();
62            assert_eq!(basic_info.rights & $test_rights, $test_rights);
63        };
64    }
65
66    #[test]
67    fn removes_duplication_from_control_ref() {
68        let ViewRefPair { control_ref, view_ref: _ } = ViewRefPair::new().unwrap();
69        assert_not_contains_rights!(control_ref, Rights::DUPLICATE);
70    }
71
72    #[test]
73    fn control_ref_can_signal() {
74        let ViewRefPair { control_ref, view_ref: _ } = ViewRefPair::new().unwrap();
75        assert_contains_rights!(control_ref, Rights::SIGNAL);
76    }
77
78    #[test]
79    fn control_ref_can_signal_peer() {
80        let ViewRefPair { control_ref, view_ref: _ } = ViewRefPair::new().unwrap();
81        assert_contains_rights!(control_ref, Rights::SIGNAL_PEER);
82    }
83
84    #[test]
85    fn view_ref_can_duplicate() {
86        let ViewRefPair { control_ref: _, view_ref } = ViewRefPair::new().unwrap();
87        assert_contains_rights!(view_ref, Rights::DUPLICATE);
88    }
89
90    #[test]
91    fn view_ref_duplicate() {
92        let ViewRefPair { control_ref: _, view_ref } = ViewRefPair::new().unwrap();
93        assert!(duplicate_view_ref(&view_ref).is_ok(), "failed to duplicate view_ref");
94    }
95}