logic-circus 0.3.0

Open source logic circuit simualtor written in Rust.
Documentation
use std::{convert::Infallible, mem};

use crate::{implemented::RustImpls, util::ContainerSizeGames, Bit, Component, Gate, GateLike};

#[derive(Clone, Debug)]
pub(crate) enum GateKind<Rust = Infallible> {
    Custom(Component<Rust>),
    Rust(RustImpls<Rust>),
}

impl<Rust> GateLike for GateKind<Rust>
where
    Rust: GateLike,
{
    /// # Safety
    /// `input.len()` must be equal to `self.num_of_inputs()`
    unsafe fn compute(&mut self, input: Vec<Bit>) -> Vec<Bit> {
        match self {
            GateKind::Custom(component) => component.compute(input),
            GateKind::Rust(component) => component.compute(input),
        }
    }

    fn num_of_inputs(&self) -> usize {
        match self {
            Self::Custom(component) => component.num_of_inputs(),
            Self::Rust(component) => component.num_of_inputs(),
        }
    }
}

impl<Rust> Gate<Rust>
where
    Rust: GateLike,
{
    /// # Safety
    /// `self.inputs.len()` must be equal to `self.kind.num_of_inputs()`, this
    /// is guaranteed if the function hasn't yet returned [`Some(_)`] or if
    /// [`self.reset()`][Gate::reset] was called
    ///
    /// `at` is in bounds for `self.inputs`
    pub(super) unsafe fn fill_input(&mut self, with: Bit, at: usize) -> Option<Vec<Bit>> {
        debug_assert!(
            self.inputs.len() > at,
            "tried to insert at [{}], but length was {}",
            at,
            self.inputs.len()
        );
        *unsafe { self.inputs.get_unchecked_mut(at) } = with;
        self.inputs_filled += 1;
        if self.inputs_filled == self.inputs.len() {
            Some(self.compute())
        } else {
            None
        }
    }

    /// # Safety
    /// `self.inputs.len()` must be equal to `self.kind.num_of_inputs`.
    unsafe fn compute(&mut self) -> Vec<Bit> {
        let inputs = mem::take(&mut self.inputs);

        self.kind.compute(inputs)
    }

    pub(super) fn reset(&mut self, full: bool) {
        self.inputs_filled = 0;
        self.inputs = Vec::zeroed(self.kind.num_of_inputs());
        if let GateKind::Custom(inner) = &mut self.kind {
            inner.reset(full);
        }
    }
}