added new Client, Entry, ClientStore structs and related logic

This commit is contained in:
NoOneBtw 2021-05-12 18:28:44 +02:00
parent e924e8efc0
commit db94c82185

358
src/clients2.rs Normal file
View file

@ -0,0 +1,358 @@
#![allow(dead_code)]
use std::{borrow::Borrow, hash::Hash};
/// Client structure.
#[derive(Clone, Debug)]
pub struct Client<T> {
window_id: T,
size: (i32, i32),
position: (i32, i32),
transient_for: Option<T>,
}
#[derive(Debug, PartialEq, Eq)]
enum Entry<T> {
Tiled(T),
Floating(T),
Transient(T),
Fullscreen(T),
Vacant,
}
type ClientSet<T> = indexmap::IndexMap<T, Client<T>>;
//type ClientSet<T> = std::collections::HashMap<T, Client<T>>;
struct ClientStore<T>
where
T: Hash + Eq,
{
tiled_clients: ClientSet<T>,
floating_clients: ClientSet<T>,
transient_clients: ClientSet<T>,
fullscreen_clients: ClientSet<T>,
}
impl<T> PartialEq for Client<T>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.window_id == other.window_id
}
}
impl<T> Eq for Client<T> where T: Eq {}
impl<T> PartialOrd for Client<T>
where
T: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.window_id.partial_cmp(&other.window_id)
}
}
impl<T> Ord for Client<T>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.window_id.cmp(&other.window_id)
}
}
impl<T> Hash for Client<T>
where
T: Hash,
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.window_id.hash(state)
}
}
impl<T> Borrow<T> for Client<T> {
fn borrow(&self) -> &T {
&self.window_id
}
}
impl<T> Client<T> {
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<T> Client<T>
where
T: Copy,
{
pub fn window_id(&self) -> T {
self.window_id
}
}
impl<T> From<Entry<T>> for Option<T> {
fn from(entry: Entry<T>) -> Self {
match entry {
Entry::Floating(c)
| Entry::Tiled(c)
| Entry::Fullscreen(c)
| Entry::Transient(c) => Some(c),
_ => None,
}
}
}
impl<'a, T> From<&'a Entry<T>> for Option<&'a T> {
fn from(entry: &'a Entry<T>) -> 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<T>> for Option<&'a mut T> {
fn from(entry: &'a mut Entry<T>) -> Self {
match entry {
Entry::Floating(c)
| Entry::Tiled(c)
| Entry::Fullscreen(c)
| Entry::Transient(c) => Some(c),
_ => None,
}
}
}
impl<T> From<Option<Entry<T>>> for Entry<T> {
fn from(opt: Option<Entry<T>>) -> Self {
match opt {
Some(entry) => entry,
None => Entry::Vacant,
}
}
}
impl<T> Entry<T> {
fn unwrap(self) -> T {
Option::<T>::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<T> Default for ClientStore<T>
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<T> ClientStore<T>
where
T: Hash + Eq + Copy,
{
fn new() -> Self {
Self::default()
}
fn insert(&mut self, entry: Entry<Client<T>>) -> Entry<&Client<T>> {
if let Some(key) =
Option::<&Client<T>>::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<Client<T>> {
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<T>> {
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<T>> {
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<Item = (&T, &Client<T>)> {
self.tiled_clients.iter()
}
fn iter_mut_tiled(&mut self) -> impl Iterator<Item = (&T, &mut Client<T>)> {
self.tiled_clients.iter_mut()
}
fn iter_floating(&self) -> impl Iterator<Item = (&T, &Client<T>)> {
self.floating_clients.iter()
}
fn iter_mut_floating(
&mut self,
) -> impl Iterator<Item = (&T, &mut Client<T>)> {
self.floating_clients.iter_mut()
}
fn iter_transient(&self) -> impl Iterator<Item = (&T, &Client<T>)> {
self.transient_clients.iter()
}
fn iter_mut_transient(
&mut self,
) -> impl Iterator<Item = (&T, &mut Client<T>)> {
self.transient_clients.iter_mut()
}
fn iter_fullscreen(&self) -> impl Iterator<Item = (&T, &Client<T>)> {
self.fullscreen_clients.iter()
}
fn iter_mut_fullscreen(
&mut self,
) -> impl Iterator<Item = (&T, &mut Client<T>)> {
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()));
}
}