From db94c82185d01d13ccce03a88f42036f2f6cf88b Mon Sep 17 00:00:00 2001 From: NoOneBtw Date: Wed, 12 May 2021 18:28:44 +0200 Subject: [PATCH] added new `Client`, `Entry`, `ClientStore` structs and related logic --- src/clients2.rs | 358 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 src/clients2.rs diff --git a/src/clients2.rs b/src/clients2.rs new file mode 100644 index 0000000..c69b2f6 --- /dev/null +++ b/src/clients2.rs @@ -0,0 +1,358 @@ +#![allow(dead_code)] +use std::{borrow::Borrow, hash::Hash}; + +/// Client structure. +#[derive(Clone, Debug)] +pub struct Client { + window_id: T, + size: (i32, i32), + position: (i32, i32), + transient_for: Option, +} + +#[derive(Debug, PartialEq, Eq)] +enum Entry { + Tiled(T), + Floating(T), + Transient(T), + Fullscreen(T), + Vacant, +} + +type ClientSet = indexmap::IndexMap>; +//type ClientSet = std::collections::HashMap>; + +struct ClientStore +where + T: Hash + Eq, +{ + tiled_clients: ClientSet, + floating_clients: ClientSet, + transient_clients: ClientSet, + fullscreen_clients: ClientSet, +} + +impl PartialEq for Client +where + T: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.window_id == other.window_id + } +} + +impl Eq for Client where T: Eq {} + +impl PartialOrd for Client +where + T: PartialOrd, +{ + fn partial_cmp(&self, other: &Self) -> Option { + self.window_id.partial_cmp(&other.window_id) + } +} + +impl Ord for Client +where + T: Ord, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.window_id.cmp(&other.window_id) + } +} + +impl Hash for Client +where + T: Hash, +{ + fn hash(&self, state: &mut H) { + self.window_id.hash(state) + } +} + +impl Borrow for Client { + fn borrow(&self) -> &T { + &self.window_id + } +} + +impl Client { + pub fn new(window_id: T) -> Self { + Self { + window_id, + size: (100, 100), + position: (0, 0), + transient_for: None, + } + } + + pub fn window_id_ref(&self) -> &T { + &self.window_id + } +} + +impl Client +where + T: Copy, +{ + pub fn window_id(&self) -> T { + self.window_id + } +} + +impl From> for Option { + fn from(entry: Entry) -> Self { + match entry { + Entry::Floating(c) + | Entry::Tiled(c) + | Entry::Fullscreen(c) + | Entry::Transient(c) => Some(c), + _ => None, + } + } +} + +impl<'a, T> From<&'a Entry> for Option<&'a T> { + fn from(entry: &'a Entry) -> Self { + match entry { + Entry::Floating(c) + | Entry::Tiled(c) + | Entry::Fullscreen(c) + | Entry::Transient(c) => Some(c), + _ => None, + } + } +} + +impl<'a, T> From<&'a mut Entry> for Option<&'a mut T> { + fn from(entry: &'a mut Entry) -> Self { + match entry { + Entry::Floating(c) + | Entry::Tiled(c) + | Entry::Fullscreen(c) + | Entry::Transient(c) => Some(c), + _ => None, + } + } +} + +impl From>> for Entry { + fn from(opt: Option>) -> Self { + match opt { + Some(entry) => entry, + None => Entry::Vacant, + } + } +} + +impl Entry { + fn unwrap(self) -> T { + Option::::from(self).unwrap() + } + + fn unwrap_ref(&self) -> &T { + Option::<&T>::from(self).unwrap() + } + + fn unwrap_mut(&mut self) -> &mut T { + Option::<&mut T>::from(self).unwrap() + } + + fn is_floating(&self) -> bool { + match self { + Self::Floating(_) => true, + _ => false, + } + } + + fn is_tiled(&self) -> bool { + match self { + Self::Tiled(_) => true, + _ => false, + } + } + + fn is_transient(&self) -> bool { + match self { + Self::Transient(_) => true, + _ => false, + } + } + + fn is_fullscreen(&self) -> bool { + match self { + Self::Fullscreen(_) => true, + _ => false, + } + } +} + +impl Default for ClientStore +where + T: Hash + Eq, +{ + fn default() -> Self { + Self { + tiled_clients: Default::default(), + floating_clients: Default::default(), + transient_clients: Default::default(), + fullscreen_clients: Default::default(), + } + } +} + +impl ClientStore +where + T: Hash + Eq + Copy, +{ + fn new() -> Self { + Self::default() + } + + fn insert(&mut self, entry: Entry>) -> Entry<&Client> { + if let Some(key) = + Option::<&Client>::from(&entry).map(|c| c.window_id()) + { + match entry { + Entry::Floating(client) => { + self.floating_clients.insert(key, client); + } + Entry::Tiled(client) => { + self.tiled_clients.insert(key, client); + } + Entry::Transient(client) => { + self.transient_clients.insert(key, client); + } + Entry::Fullscreen(client) => { + self.fullscreen_clients.insert(key, client); + } + _ => unreachable!(), + } + + self.get(&key).into() + } else { + Entry::Vacant + } + } + + fn remove(&mut self, key: &T) -> Entry> { + if let Some(client) = self.tiled_clients.remove(key) { + Entry::Tiled(client) + } else if let Some(client) = self.floating_clients.remove(key) { + Entry::Floating(client) + } else if let Some(client) = self.transient_clients.remove(key) { + Entry::Transient(client) + } else if let Some(client) = self.fullscreen_clients.remove(key) { + Entry::Fullscreen(client) + } else { + Entry::Vacant + } + } + + fn get(&self, key: &T) -> Entry<&Client> { + if let Some(client) = self.tiled_clients.get(key) { + Entry::Tiled(client) + } else if let Some(client) = self.floating_clients.get(key) { + Entry::Floating(client) + } else if let Some(client) = self.transient_clients.get(key) { + Entry::Transient(client) + } else if let Some(client) = self.fullscreen_clients.get(key) { + Entry::Fullscreen(client) + } else { + Entry::Vacant + } + } + + fn get_mut(&mut self, key: &T) -> Entry<&mut Client> { + if let Some(client) = self.tiled_clients.get_mut(key) { + Entry::Tiled(client) + } else if let Some(client) = self.floating_clients.get_mut(key) { + Entry::Floating(client) + } else if let Some(client) = self.transient_clients.get_mut(key) { + Entry::Transient(client) + } else if let Some(client) = self.fullscreen_clients.get_mut(key) { + Entry::Fullscreen(client) + } else { + Entry::Vacant + } + } + + fn contains(&self, key: &T) -> bool { + self.tiled_clients.contains_key(key) + || self.floating_clients.contains_key(key) + || self.transient_clients.contains_key(key) + || self.fullscreen_clients.contains_key(key) + } + + fn iter_tiled(&self) -> impl Iterator)> { + self.tiled_clients.iter() + } + + fn iter_mut_tiled(&mut self) -> impl Iterator)> { + self.tiled_clients.iter_mut() + } + + fn iter_floating(&self) -> impl Iterator)> { + self.floating_clients.iter() + } + + fn iter_mut_floating( + &mut self, + ) -> impl Iterator)> { + self.floating_clients.iter_mut() + } + + fn iter_transient(&self) -> impl Iterator)> { + self.transient_clients.iter() + } + + fn iter_mut_transient( + &mut self, + ) -> impl Iterator)> { + self.transient_clients.iter_mut() + } + + fn iter_fullscreen(&self) -> impl Iterator)> { + self.fullscreen_clients.iter() + } + + fn iter_mut_fullscreen( + &mut self, + ) -> impl Iterator)> { + self.fullscreen_clients.iter_mut() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn clientstore_insert_contain() { + let client = Client::new(1u64); + + let mut client_store = ClientStore::new(); + client_store.insert(Entry::Tiled(client.clone())); + + assert!(client_store.contains(client.borrow())); + assert!(client_store.contains(&1)); + + let client2 = Client::new(3u64); + client_store.insert(Entry::Floating(client2.clone())); + + assert!(client_store.contains(&client.borrow())); + assert!(client_store.contains(&1)); + + assert!(client_store.contains(&client2.borrow())); + assert!(client_store.contains(&3)); + + assert_eq!( + Entry::Tiled(client.clone()), + client_store.remove(&client.borrow()) + ); + assert_eq!(Entry::Vacant, client_store.remove(&client.borrow())); + assert_eq!(Entry::Vacant, client_store.remove(&1)); + + assert!(client_store.contains(&client2.borrow())); + } +}