use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum ObjectType {
Window = 0,
Tab = 1,
Pane = 2,
MuxWindow = 3,
MuxTab = 4,
MuxPane = 5,
}
impl fmt::Display for ObjectType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ObjectType::Window => write!(f, "Window"),
ObjectType::Tab => write!(f, "Tab"),
ObjectType::Pane => write!(f, "Pane"),
ObjectType::MuxWindow => write!(f, "MuxWindow"),
ObjectType::MuxTab => write!(f, "MuxTab"),
ObjectType::MuxPane => write!(f, "MuxPane"),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ObjectHandle {
object_type: ObjectType,
id: u64,
generation: u32,
}
impl ObjectHandle {
pub const fn new(object_type: ObjectType, id: u64, generation: u32) -> Self {
Self {
object_type,
id,
generation,
}
}
#[inline]
pub const fn object_type(&self) -> ObjectType {
self.object_type
}
#[inline]
pub const fn id(&self) -> u64 {
self.id
}
#[inline]
pub const fn generation(&self) -> u32 {
self.generation
}
#[inline]
pub const fn is_valid(&self, current_generation: u32) -> bool {
self.generation == current_generation
}
#[inline]
pub const fn next_generation(&self) -> Self {
Self {
object_type: self.object_type,
id: self.id,
generation: self.generation.wrapping_add(1),
}
}
}
impl fmt::Debug for ObjectHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ObjectHandle({}, id={}, gen={})",
self.object_type, self.id, self.generation
)
}
}
impl fmt::Display for ObjectHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}#{}", self.object_type, self.id)
}
}
unsafe impl Send for ObjectHandle {}
unsafe impl Sync for ObjectHandle {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_handle_creation() {
let handle = ObjectHandle::new(ObjectType::Window, 42, 1);
assert_eq!(handle.object_type(), ObjectType::Window);
assert_eq!(handle.id(), 42);
assert_eq!(handle.generation(), 1);
}
#[test]
fn test_handle_equality() {
let h1 = ObjectHandle::new(ObjectType::Tab, 10, 1);
let h2 = ObjectHandle::new(ObjectType::Tab, 10, 1);
let h3 = ObjectHandle::new(ObjectType::Tab, 10, 2);
let h4 = ObjectHandle::new(ObjectType::Pane, 10, 1);
assert_eq!(h1, h2);
assert_ne!(h1, h3); assert_ne!(h1, h4); }
#[test]
fn test_handle_validation() {
let handle = ObjectHandle::new(ObjectType::Window, 1, 5);
assert!(handle.is_valid(5));
assert!(!handle.is_valid(4));
assert!(!handle.is_valid(6));
}
#[test]
fn test_next_generation() {
let h1 = ObjectHandle::new(ObjectType::Pane, 100, 1);
let h2 = h1.next_generation();
assert_eq!(h2.id(), 100);
assert_eq!(h2.object_type(), ObjectType::Pane);
assert_eq!(h2.generation(), 2);
assert!(!h1.is_valid(2));
assert!(h2.is_valid(2));
}
#[test]
fn test_generation_wrapping() {
let handle = ObjectHandle::new(ObjectType::Window, 1, u32::MAX);
let next = handle.next_generation();
assert_eq!(next.generation(), 0); }
#[test]
fn test_handle_copy() {
let h1 = ObjectHandle::new(ObjectType::Tab, 5, 3);
let h2 = h1; assert_eq!(h1, h2);
assert_eq!(h1.id(), h2.id()); }
#[test]
fn test_object_type_display() {
assert_eq!(ObjectType::Window.to_string(), "Window");
assert_eq!(ObjectType::Tab.to_string(), "Tab");
assert_eq!(ObjectType::Pane.to_string(), "Pane");
assert_eq!(ObjectType::MuxWindow.to_string(), "MuxWindow");
assert_eq!(ObjectType::MuxTab.to_string(), "MuxTab");
assert_eq!(ObjectType::MuxPane.to_string(), "MuxPane");
}
#[test]
fn test_handle_display() {
let handle = ObjectHandle::new(ObjectType::Window, 42, 1);
assert_eq!(handle.to_string(), "Window#42");
}
#[test]
fn test_handle_debug() {
let handle = ObjectHandle::new(ObjectType::Pane, 7, 3);
let debug_str = format!("{:?}", handle);
assert!(debug_str.contains("Pane"));
assert!(debug_str.contains("id=7"));
assert!(debug_str.contains("gen=3"));
}
}