logic-circus 0.3.0

Open source logic circuit simualtor written in Rust.
Documentation
use crate::{
    gate::GateKind, implemented::RustImpls, util::ContainerSizeGames, Component, ComponentBuilder,
    Gate, GateLike, Sequal,
};

impl<Rust> Default for ComponentBuilder<Rust> {
    fn default() -> Self {
        Self {
            gates: Vec::default(),
            sequals: Vec::default(),
            outputs: usize::default(),
        }
    }
}

impl<Rust> ComponentBuilder<Rust> {
    /// Add a gate to the component
    ///
    /// `gate` is the gate you want to add.
    ///
    /// `sequals` dictate where the outputs of the gate go, in other words the
    /// wiring, these `sequal`s are in order, so the `gate`'s first `output`
    /// will go to the first `sequal` and so on.
    ///
    /// a sequal can either be another gate or one of the components outputs.
    ///
    /// if you want to send an output to several places it must be done
    /// indirectly, you should take a look at [`Gate::dup`].
    pub fn gate(mut self, gate: Gate<Rust>, sequals: Vec<Sequal>) -> Self {
        self.push_sequals(sequals);
        self.gates.push(gate);
        self
    }

    fn push_sequals(&mut self, sequals: Vec<Sequal>) -> &mut Self {
        self.outputs += sequals
            .iter()
            .filter(|x| matches!(x, Sequal::End { .. }))
            .count();
        self.sequals.push(sequals);
        self
    }

    /// Tell the component where it's inputs should go
    ///
    /// after you've added many gates to your component you still need to tell
    /// the component where to start, once you do that your component is ready
    /// and it will be returned from the function
    pub fn inputs(mut self, inputs: Vec<Sequal>) -> Component<Rust> {
        self.push_sequals(inputs);
        Component::from_raw_parts(self.gates, self.sequals, self.outputs)
    }
}

impl<Rust> Component<Rust> {
    /// Aquire a [`ComponentBuilder`]
    pub fn builder() -> ComponentBuilder<Rust> {
        ComponentBuilder::default()
    }

    /// Create a component out of a single gate
    ///
    /// this is mostly useless since the gate itself can probably do whatever
    /// you need and exists mostly for tests
    pub fn single_gate(gate: Gate<Rust>, num_of_outputs: usize) -> Self {
        let inputs = gate.inputs.len();
        Self::builder()
            .gate(gate, (0..num_of_outputs).map(Sequal::end).collect())
            .inputs((0..inputs).map(|entry| Sequal::gate(0, entry)).collect())
    }

    /// Create a component from it's raw parts
    ///
    /// in `sequals` each `Vec<Sequal>` corresponds to a single gates sequals
    /// (in the same index) and the last corresponds to the components inputs
    /// `outputs` is the amount of outputs your component has
    pub fn from_raw_parts(
        gates: Vec<Gate<Rust>>,
        sequals: Vec<Vec<Sequal>>,
        outputs: usize,
    ) -> Self {
        debug_assert_eq!(
            gates.len(),
            sequals.len() - 1,
            "read the documentation of this function"
        );

        Self {
            gates,
            sequals,
            outputs,
        }
    }
}

impl Sequal {
    /// Another gate
    pub fn gate(index: usize, entry: usize) -> Self {
        Self::Gate { index, entry }
    }

    /// An output of the component
    pub fn end(output: usize) -> Self {
        Self::End { output }
    }
}

impl<Rust> Gate<Rust>
where
    Rust: GateLike,
{
    fn new(kind: GateKind<Rust>) -> Self {
        Self {
            inputs: Vec::zeroed(kind.num_of_inputs()),
            inputs_filled: 0,
            kind,
        }
    }

    /// Create a gate from a custom component
    pub fn component(component: Component<Rust>) -> Self {
        Self::new(GateKind::Custom(component))
    }
    /// Create a gate from logic you wrote in rust
    pub fn rust(gate: Rust) -> Self {
        Self::new(GateKind::Rust(RustImpls::User(gate)))
    }
    /// A duplicator, this is akin to a wire splitting
    pub fn dup(amount: usize) -> Self {
        Self::new(GateKind::Rust(RustImpls::Dup(amount)))
    }
    /// This holds a single bit of memory in between CPU ticks
    pub fn mem() -> Self {
        Self::new(GateKind::Rust(RustImpls::Mem(bool::default())))
    }
    /// A Not gate
    pub fn not() -> Self {
        Self::new(GateKind::Rust(RustImpls::Not))
    }
    /// A Nand gate
    pub fn nand() -> Self {
        Self::new(GateKind::Rust(RustImpls::Nand))
    }
    /// A bitwise And gate
    pub fn and() -> Self {
        Self::new(GateKind::Rust(RustImpls::And))
    }
    /// A bitwise Or gate
    pub fn or() -> Self {
        Self::new(GateKind::Rust(RustImpls::Or))
    }
    /// A Nor gate
    pub fn nor() -> Self {
        Self::new(GateKind::Rust(RustImpls::Nor))
    }
    /// An Xor gate
    pub fn xor() -> Self {
        Self::new(GateKind::Rust(RustImpls::Xor))
    }
}