//! A place in a CPN. use std::hash::{Hash, Hasher}; use std::ops::AddAssign; /// Token capacity of a `Place`. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Capacity { /// The `Place` can only hold this many tokens. Limited(usize), /// The `Place` can hold an arbitrary number of tokens. Infinite, } impl AddAssign for Capacity { fn add_assign(&mut self, n: usize) { if let Self::Limited(cap) = self { *cap += n; } } } /// A place in a CPN. /// /// A place has a name, and a capacity. If not explicitly set using `with_capacity`, the capacity /// defaults to infinite. #[derive(Debug, Clone)] pub struct Place { name: String, capacity: Capacity, } impl Place { /// Construct a new place with the given name, and infinite capacity. pub fn new(name: S) -> Self where S: Into, { Self { name: name.into(), capacity: Capacity::Infinite, } } /// Limit the capacity of this place to `cap` tokens. /// /// # Panics /// /// Panics if `cap` is 0. pub fn with_capacity(mut self, cap: usize) -> Self { assert!(cap > 0, "A capacity of 0 makes no sense!"); self.capacity = Capacity::Limited(cap); self } /// Get a reference to the name of this place. pub fn name(&self) -> &str { &self.name } /// Get the capacity of this place. pub fn capacity(&self) -> Capacity { self.capacity } } impl PartialEq for Place { fn eq(&self, other: &Self) -> bool { self.name == other.name } } impl Eq for Place {} impl Hash for Place { fn hash(&self, state: &mut H) where H: Hasher, { state.write(self.name.as_bytes()); } } impl From<&str> for Place { fn from(s: &str) -> Self { Self::new(s) } } impl From for Place { fn from(s: String) -> Self { Self { name: s, capacity: Capacity::Infinite, } } }