use crate::{
atom::Atom,
process::RemotePid,
term::{Term, boxed::ExternalPid},
};
#[derive(Copy, Clone, Debug)]
pub enum PidRef {
Local(u64),
Remote(ExternalPid),
}
impl PidRef {
pub fn new(term: Term) -> Option<Self> {
if let Some(pid) = term.as_pid() {
return Some(Self::Local(pid));
}
ExternalPid::new(term).map(Self::Remote)
}
#[must_use]
pub fn pid_number(self) -> u64 {
match self {
Self::Local(pid) => pid,
Self::Remote(pid) => pid.pid_number(),
}
}
#[must_use]
pub fn serial(self) -> u64 {
match self {
Self::Local(_) => 0,
Self::Remote(pid) => pid.serial(),
}
}
#[must_use]
pub fn node(self) -> Option<Atom> {
match self {
Self::Local(_) => None,
Self::Remote(pid) => pid.node(),
}
}
#[must_use]
pub fn remote_pid(self) -> Option<RemotePid> {
let Self::Remote(pid) = self else {
return None;
};
Some(RemotePid {
node: pid.node()?,
pid_number: pid.pid_number(),
serial: pid.serial(),
})
}
#[must_use]
pub const fn is_local(self) -> bool {
matches!(self, Self::Local(_))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::term::boxed::write_external_pid;
#[test]
fn pid_ref_wraps_local_immediate_pid() {
let pid = PidRef::new(Term::pid(42)).expect("local pid");
assert!(pid.is_local());
assert_eq!(pid.pid_number(), 42);
assert_eq!(pid.serial(), 0);
assert_eq!(pid.node(), None);
}
#[test]
fn pid_ref_wraps_remote_boxed_pid() {
let mut heap = [0_u64; 4];
let term = write_external_pid(&mut heap, Atom::OK, 99, 7).expect("external pid fits");
let pid = PidRef::new(term).expect("remote pid");
assert!(!pid.is_local());
assert_eq!(pid.pid_number(), 99);
assert_eq!(pid.serial(), 7);
assert_eq!(pid.node(), Some(Atom::OK));
}
}