wayland_backend/rs/
map.rs

1//! Wayland objects map
2
3use crate::protocol::Interface;
4
5use std::cmp::Ordering;
6
7/// Limit separating server-created from client-created objects IDs in the namespace
8pub const SERVER_ID_LIMIT: u32 = 0xFF00_0000;
9
10/// The representation of a protocol object
11#[derive(Debug, Clone)]
12pub struct Object<Data> {
13    /// Interface name of this object
14    pub interface: &'static Interface,
15    /// Version of this object
16    pub version: u32,
17    /// ObjectData associated to this object (ex: its event queue client side)
18    pub data: Data,
19}
20
21/// A holder for the object store of a connection
22///
23/// Keeps track of which object id is associated to which
24/// interface object, and which is currently unused.
25#[derive(Debug, Default)]
26pub struct ObjectMap<Data> {
27    client_objects: Vec<Option<Object<Data>>>,
28    server_objects: Vec<Option<Object<Data>>>,
29}
30
31impl<Data: Clone> ObjectMap<Data> {
32    /// Create a new empty object map
33    pub fn new() -> Self {
34        Self { client_objects: Vec::new(), server_objects: Vec::new() }
35    }
36
37    /// Find an object in the store
38    pub fn find(&self, id: u32) -> Option<Object<Data>> {
39        if id == 0 {
40            None
41        } else if id >= SERVER_ID_LIMIT {
42            self.server_objects.get((id - SERVER_ID_LIMIT) as usize).and_then(Clone::clone)
43        } else {
44            self.client_objects.get((id - 1) as usize).and_then(Clone::clone)
45        }
46    }
47
48    /// Remove an object from the store
49    ///
50    /// Does nothing if the object didn't previously exists
51    pub fn remove(&mut self, id: u32) {
52        if id == 0 {
53            // nothing
54        } else if id >= SERVER_ID_LIMIT {
55            if let Some(place) = self.server_objects.get_mut((id - SERVER_ID_LIMIT) as usize) {
56                *place = None;
57            }
58        } else if let Some(place) = self.client_objects.get_mut((id - 1) as usize) {
59            *place = None;
60        }
61    }
62
63    /// Insert given object for given id
64    ///
65    /// Can fail if the requested id is not the next free id of this store.
66    /// (In which case this is a protocol error)
67    pub fn insert_at(&mut self, id: u32, object: Object<Data>) -> Result<(), ()> {
68        if id == 0 {
69            Err(())
70        } else if id >= SERVER_ID_LIMIT {
71            insert_in_at(&mut self.server_objects, (id - SERVER_ID_LIMIT) as usize, object)
72        } else {
73            insert_in_at(&mut self.client_objects, (id - 1) as usize, object)
74        }
75    }
76
77    /// Allocate a new id for an object in the client namespace
78    pub fn client_insert_new(&mut self, object: Object<Data>) -> u32 {
79        insert_in(&mut self.client_objects, object) + 1
80    }
81
82    /// Allocate a new id for an object in the server namespace
83    pub fn server_insert_new(&mut self, object: Object<Data>) -> u32 {
84        insert_in(&mut self.server_objects, object) + SERVER_ID_LIMIT
85    }
86
87    /// Mutably access an object of the map
88    pub fn with<T, F: FnOnce(&mut Object<Data>) -> T>(&mut self, id: u32, f: F) -> Result<T, ()> {
89        if id == 0 {
90            Err(())
91        } else if id >= SERVER_ID_LIMIT {
92            if let Some(&mut Some(ref mut obj)) =
93                self.server_objects.get_mut((id - SERVER_ID_LIMIT) as usize)
94            {
95                Ok(f(obj))
96            } else {
97                Err(())
98            }
99        } else if let Some(&mut Some(ref mut obj)) = self.client_objects.get_mut((id - 1) as usize)
100        {
101            Ok(f(obj))
102        } else {
103            Err(())
104        }
105    }
106
107    pub fn all_objects(&self) -> impl Iterator<Item = (u32, &Object<Data>)> {
108        let client_side_iter = self
109            .client_objects
110            .iter()
111            .enumerate()
112            .flat_map(|(idx, obj)| obj.as_ref().map(|obj| (idx as u32 + 1, obj)));
113
114        let server_side_iter = self
115            .server_objects
116            .iter()
117            .enumerate()
118            .flat_map(|(idx, obj)| obj.as_ref().map(|obj| (idx as u32 + SERVER_ID_LIMIT, obj)));
119
120        client_side_iter.chain(server_side_iter)
121    }
122}
123
124// insert a new object in a store at the first free place
125fn insert_in<Data>(store: &mut Vec<Option<Object<Data>>>, object: Object<Data>) -> u32 {
126    match store.iter().position(Option::is_none) {
127        Some(id) => {
128            store[id] = Some(object);
129            id as u32
130        }
131        None => {
132            store.push(Some(object));
133            (store.len() - 1) as u32
134        }
135    }
136}
137
138// insert an object at a given place in a store
139fn insert_in_at<Data>(
140    store: &mut Vec<Option<Object<Data>>>,
141    id: usize,
142    object: Object<Data>,
143) -> Result<(), ()> {
144    match id.cmp(&store.len()) {
145        Ordering::Greater => Err(()),
146        Ordering::Equal => {
147            store.push(Some(object));
148            Ok(())
149        }
150        Ordering::Less => {
151            let previous = &mut store[id];
152            if !previous.is_none() {
153                return Err(());
154            }
155            *previous = Some(object);
156            Ok(())
157        }
158    }
159}