logic_circus/
gate.rs

1use std::{convert::Infallible, mem};
2
3use crate::{implemented::RustImpls, util::ContainerSizeGames, Bit, Component, Gate, GateLike};
4
5#[derive(Clone, Debug)]
6pub(crate) enum GateKind<Rust = Infallible> {
7    Custom(Component<Rust>),
8    Rust(RustImpls<Rust>),
9}
10
11impl<Rust> GateLike for GateKind<Rust>
12where
13    Rust: GateLike,
14{
15    /// # Safety
16    /// `input.len()` must be equal to `self.num_of_inputs()`
17    unsafe fn compute(&mut self, input: Vec<Bit>) -> Vec<Bit> {
18        match self {
19            GateKind::Custom(component) => component.compute(input),
20            GateKind::Rust(component) => component.compute(input),
21        }
22    }
23
24    fn num_of_inputs(&self) -> usize {
25        match self {
26            Self::Custom(component) => component.num_of_inputs(),
27            Self::Rust(component) => component.num_of_inputs(),
28        }
29    }
30}
31
32impl<Rust> Gate<Rust>
33where
34    Rust: GateLike,
35{
36    /// # Safety
37    /// `self.inputs.len()` must be equal to `self.kind.num_of_inputs()`, this
38    /// is guaranteed if the function hasn't yet returned [`Some(_)`] or if
39    /// [`self.reset()`][Gate::reset] was called
40    ///
41    /// `at` is in bounds for `self.inputs`
42    pub(super) unsafe fn fill_input(&mut self, with: Bit, at: usize) -> Option<Vec<Bit>> {
43        debug_assert!(
44            self.inputs.len() > at,
45            "tried to insert at [{}], but length was {}",
46            at,
47            self.inputs.len()
48        );
49        *unsafe { self.inputs.get_unchecked_mut(at) } = with;
50        self.inputs_filled += 1;
51        if self.inputs_filled == self.inputs.len() {
52            Some(self.compute())
53        } else {
54            None
55        }
56    }
57
58    /// # Safety
59    /// `self.inputs.len()` must be equal to `self.kind.num_of_inputs`.
60    unsafe fn compute(&mut self) -> Vec<Bit> {
61        let inputs = mem::take(&mut self.inputs);
62
63        self.kind.compute(inputs)
64    }
65
66    pub(super) fn reset(&mut self, full: bool) {
67        self.inputs_filled = 0;
68        self.inputs = Vec::zeroed(self.kind.num_of_inputs());
69        if let GateKind::Custom(inner) = &mut self.kind {
70            inner.reset(full);
71        }
72    }
73}