#![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)] pub enum Entry { Tiled(T), Floating(T), Transient(T), Fullscreen(T), Vacant, } type ClientSet = indexmap::IndexMap>; //type ClientSet = std::collections::HashMap>; pub 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 } /// Get a mutable reference to the client's size. pub fn size_mut(&mut self) -> &mut (i32, i32) { &mut self.size } /// Get a mutable reference to the client's position. pub fn position_mut(&mut self) -> &mut (i32, i32) { &mut self.position } /// Get a reference to the client's size. pub fn size(&self) -> &(i32, i32) { &self.size } /// Get a reference to the client's position. pub fn position(&self) -> &(i32, i32) { &self.position } } 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 { pub fn unwrap(self) -> T { Option::::from(self).unwrap() } pub fn unwrap_ref(&self) -> &T { Option::<&T>::from(self).unwrap() } pub fn unwrap_mut(&mut self) -> &mut T { Option::<&mut T>::from(self).unwrap() } pub fn is_floating(&self) -> bool { match self { Self::Floating(_) => true, _ => false, } } pub fn is_tiled(&self) -> bool { match self { Self::Tiled(_) => true, _ => false, } } pub fn is_transient(&self) -> bool { match self { Self::Transient(_) => true, _ => false, } } pub 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, { pub fn new() -> Self { Self::default() } pub 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 } } pub 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 } } pub 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 } } pub 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 } } pub 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) } pub fn iter_tiled( &self, ) -> impl Iterator)> { self.tiled_clients.iter() } pub fn iter_mut_tiled( &mut self, ) -> impl Iterator)> { self.tiled_clients.iter_mut() } pub fn iter_floating( &self, ) -> impl Iterator)> { self.floating_clients.iter() } pub fn iter_mut_floating( &mut self, ) -> impl Iterator)> { self.floating_clients.iter_mut() } pub fn iter_transient( &self, ) -> impl Iterator)> { self.transient_clients.iter() } pub fn iter_mut_transient( &mut self, ) -> impl Iterator)> { self.transient_clients.iter_mut() } pub fn iter_fullscreen( &self, ) -> impl Iterator)> { self.fullscreen_clients.iter() } pub 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())); } }