use crate::client::Client;
use crate::object::MessageReceiver;
use anyhow::Error;
use fuchsia_wayland_core as wl;
use std::mem;
pub struct RegistryBuilder {
globals: Vec<Global>,
}
impl RegistryBuilder {
pub fn new() -> Self {
RegistryBuilder { globals: Vec::new() }
}
pub fn add_global<
I: wl::Interface + 'static,
F: FnMut(wl::ObjectId, u32, &mut Client) -> Result<Box<dyn MessageReceiver>, Error>
+ Send
+ 'static,
>(
&mut self,
_: I,
bind: F,
) -> &mut Self {
self.globals.push(Global {
name: I::NAME,
version: I::VERSION,
requests: &I::REQUESTS,
bind_fn: Box::new(bind),
});
self
}
pub fn build(&mut self) -> Registry {
Registry { globals: mem::replace(&mut self.globals, vec![]) }
}
}
pub struct Registry {
globals: Vec<Global>,
}
impl Registry {
pub fn globals(&mut self) -> &mut [Global] {
self.globals.as_mut_slice()
}
}
pub struct Global {
name: &'static str,
version: u32,
requests: &'static wl::MessageGroupSpec,
bind_fn: Box<
dyn FnMut(wl::ObjectId, u32, &mut Client) -> Result<Box<dyn MessageReceiver>, Error> + Send,
>,
}
impl Global {
pub fn interface(&self) -> &str {
self.name
}
pub fn version(&self) -> u32 {
self.version
}
pub fn request_spec(&self) -> &'static wl::MessageGroupSpec {
self.requests
}
pub fn bind(
&mut self,
id: wl::ObjectId,
version: u32,
client: &mut Client,
) -> Result<Box<dyn MessageReceiver>, Error> {
(*self.bind_fn)(id, version, client)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
use fuchsia_sync::Mutex;
use fuchsia_wayland_core::{Interface, IntoMessage};
use {fuchsia_async as fasync, zx};
use crate::display::Display;
use crate::object::RequestDispatcher;
use crate::test_protocol::*;
#[test]
fn registry_bind() -> Result<(), Error> {
#[derive(Default)]
struct Counts {
interface_1_bind_count: usize,
interface_2_bind_count: usize,
}
let counts: Arc<Mutex<Counts>> = Arc::new(Mutex::new(Default::default()));
let mut registry = RegistryBuilder::new();
{
let counts = counts.clone();
registry.add_global(TestInterface, move |_, _, _| {
counts.lock().interface_1_bind_count += 1;
Ok(Box::new(RequestDispatcher::new(TestReceiver::new())))
});
}
{
let counts = counts.clone();
registry.add_global(TestInterface2, move |_, _, _| {
counts.lock().interface_2_bind_count += 1;
Ok(Box::new(RequestDispatcher::new(TestReceiver::new())))
});
}
let registry = registry.build();
assert_eq!(0, counts.lock().interface_1_bind_count);
assert_eq!(0, counts.lock().interface_2_bind_count);
let (c1, _c2) = zx::Channel::create();
let _executor = fasync::LocalExecutor::new();
let display = Display::new_no_scenic(registry).expect("Failed to create display");
let mut client = Client::new(fasync::Channel::from_channel(c1), display.clone());
let receivers: Vec<Box<dyn MessageReceiver>> = display
.registry()
.lock()
.globals
.iter_mut()
.map(|g| g.bind(0, 0, &mut client).unwrap())
.collect();
for (id, r) in receivers.into_iter().enumerate() {
client.add_object_raw(id as u32, r, &TestInterface::REQUESTS)?;
}
assert_eq!(1, counts.lock().interface_1_bind_count);
assert_eq!(1, counts.lock().interface_2_bind_count);
assert_eq!(0, client.get_object::<TestReceiver>(0)?.count());
assert_eq!(0, client.get_object::<TestReceiver>(1)?.count());
client.handle_message(TestMessage::Message1.into_message(0)?)?;
client.handle_message(TestMessage::Message1.into_message(1)?)?;
assert_eq!(1, counts.lock().interface_1_bind_count);
assert_eq!(1, counts.lock().interface_2_bind_count);
assert_eq!(1, client.get_object::<TestReceiver>(0)?.count());
assert_eq!(1, client.get_object::<TestReceiver>(1)?.count());
Ok(())
}
}