use core::fmt;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ProcessIdentity {
pub pid: u32,
pub start_key: u64,
}
impl ProcessIdentity {
#[must_use]
pub const fn new(pid: u32, start_key: u64) -> Self {
Self { pid, start_key }
}
#[must_use]
pub const fn is_reuse_of(&self, other: &Self) -> bool {
self.pid == other.pid && self.start_key != other.start_key
}
}
impl fmt::Display for ProcessIdentity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.pid)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UserIdentity {
pub uid: u32,
pub name: Option<Box<str>>,
}
impl UserIdentity {
#[must_use]
pub fn display_name(&self) -> String {
match &self.name {
Some(name) => name.to_string(),
None => self.uid.to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn identity_requires_both_pid_and_start_key_to_match() {
let a = ProcessIdentity::new(31842, 900_100);
let b = ProcessIdentity::new(31842, 900_100);
let recycled = ProcessIdentity::new(31842, 977_400);
let other = ProcessIdentity::new(1221, 900_100);
assert_eq!(a, b);
assert_ne!(a, recycled);
assert_ne!(a, other);
}
#[test]
fn pid_reuse_is_detected_and_a_different_pid_is_not_reuse() {
let pinned = ProcessIdentity::new(31842, 900_100);
let recycled = ProcessIdentity::new(31842, 977_400);
let unrelated = ProcessIdentity::new(1221, 977_400);
assert!(
recycled.is_reuse_of(&pinned),
"same PID, different start key"
);
assert!(!pinned.is_reuse_of(&pinned), "identical is not reuse");
assert!(
!unrelated.is_reuse_of(&pinned),
"different PID is not reuse"
);
}
#[test]
fn display_shows_only_the_pid() {
assert_eq!(ProcessIdentity::new(31842, 900_100).to_string(), "31842");
}
#[test]
fn unresolvable_user_names_fall_back_to_the_numeric_id() {
let named = UserIdentity {
uid: 501,
name: Some("gabor".into()),
};
let anonymous = UserIdentity {
uid: 501,
name: None,
};
assert_eq!(named.display_name(), "gabor");
assert_eq!(anonymous.display_name(), "501");
}
}