use core::{cmp::Ordering, marker::PhantomData};
use super::{Gate, ReleaseDrivenGate};
pub struct And<A, B>(PhantomData<fn() -> (A, B)>);
impl<A, B> core::fmt::Debug for And<A, B> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("And")
}
}
impl<A, B> Clone for And<A, B> {
fn clone(&self) -> Self {
*self
}
}
impl<A, B> Copy for And<A, B> {}
impl<A, B> Default for And<A, B> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<A: ReleaseDrivenGate, B: ReleaseDrivenGate> Gate for And<A, B> {
type Dep = (A::Dep, B::Dep);
type Progress = AndProgress<A::Progress, B::Progress>;
fn deliverable(progress: &Self::Progress, sender: u32, dep: &Self::Dep) -> bool {
A::deliverable(progress.left(), sender, &dep.0)
&& B::deliverable(progress.right(), sender, &dep.1)
}
fn advance(progress: &mut Self::Progress, sender: u32, dep: &Self::Dep) {
A::advance(&mut progress.left, sender, &dep.0);
B::advance(&mut progress.right, sender, &dep.1);
}
fn stale(progress: &Self::Progress, sender: u32, dep: &Self::Dep) -> bool {
A::stale(progress.left(), sender, &dep.0) || B::stale(progress.right(), sender, &dep.1)
}
}
impl<A: ReleaseDrivenGate, B: ReleaseDrivenGate> ReleaseDrivenGate for And<A, B> {}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct AndProgress<A, B> {
left: A,
right: B,
}
impl<A, B> AndProgress<A, B> {
#[must_use]
pub const fn new(left: A, right: B) -> Self {
Self { left, right }
}
#[must_use]
pub const fn left(&self) -> &A {
&self.left
}
#[must_use]
pub const fn right(&self) -> &B {
&self.right
}
#[must_use]
pub fn into_parts(self) -> (A, B) {
(self.left, self.right)
}
}
impl<A: PartialOrd, B: PartialOrd> PartialOrd for AndProgress<A, B> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
use Ordering::{Equal, Greater, Less};
match (
self.left.partial_cmp(&other.left)?,
self.right.partial_cmp(&other.right)?,
) {
(Equal, ordering) | (ordering, Equal) => Some(ordering),
(Less, Less) => Some(Less),
(Greater, Greater) => Some(Greater),
(Less, Greater) | (Greater, Less) => None,
}
}
}