use core::cmp::Ordering;
use core::fmt::Debug;
use core::hash::Hash;
#[cfg(feature = "dev")]
use arbitrary::Arbitrary;
use order_theory::{GreatestElement, LowerSemilattice};
use crate::prelude::*;
pub use core::num::NonZeroU64;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "dev", derive(Arbitrary))]
pub struct AreaOfInterest {
area: Area,
max_count: NonZeroU64,
max_size: u64,
}
impl AreaOfInterest {
pub fn new(area: Area, max_count: NonZeroU64, max_size: u64) -> Self {
Self {
area,
max_count,
max_size,
}
}
pub fn area(&self) -> &Area {
&self.area
}
pub fn max_count(&self) -> NonZeroU64 {
self.max_count
}
pub fn max_size(&self) -> u64 {
self.max_size
}
pub fn set_area(&mut self, new_area: Area) {
self.area = new_area;
}
pub fn set_max_count(&mut self, new_max_count: NonZeroU64) {
self.max_count = new_max_count;
}
pub fn set_max_size(&mut self, new_max_size: u64) {
self.max_size = new_max_size;
}
}
impl AreaOfInterest {
pub fn intersection(&self, other: &Self) -> Result<Self, EmptyGrouping> {
Ok(Self::new(
self.area().intersection(other.area())?,
core::cmp::min(self.max_count(), other.max_count()),
self.max_size().greatest_lower_bound(&other.max_size()),
))
}
}
impl PartialOrd<Self> for AreaOfInterest {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (
self.area().partial_cmp(other.area())?,
self.max_count().cmp(&other.max_count()),
self.max_size().cmp(&other.max_size()),
) {
(Ordering::Equal, Ordering::Equal, Ordering::Equal) => Some(Ordering::Equal),
(area_cmp, count_cmp, size_cmp) => {
if area_cmp.is_le() && count_cmp.is_le() && size_cmp.is_le() {
Some(Ordering::Less)
} else if area_cmp.is_ge() && count_cmp.is_ge() && size_cmp.is_ge() {
Some(Ordering::Greater)
} else {
None
}
}
}
}
}
impl GreatestElement for AreaOfInterest {
fn greatest() -> Self {
Self::new(Area::greatest(), NonZeroU64::MAX, u64::MAX)
}
fn is_greatest(&self) -> bool {
self.area().is_greatest()
&& self.max_count() == NonZeroU64::MAX
&& self.max_size() == u64::MAX
}
}