rust_play_digital 0.1.3

This crate implements analog functions of digital circuits.You can build and match different circuits as you want.
Documentation
use crate::common::{Digital, TwoInputDigital};
use crate::output::State::{ONE, ZERO};
use crate::output::{DigitalState, State};
use std::rc::Rc;
use crate::Digital1Line;

///XORElectric structure represent the XOR logic circuit
pub struct XORElectric {
    input_a: Option<Rc<dyn Digital1Line>>,
    input_b: Option<Rc<dyn Digital1Line>>,
    input_a_state: DigitalState,
    input_b_state: DigitalState,
    output_state: DigitalState,
    times: usize,
}
#[allow(unused)]
impl Digital for XORElectric {
    fn get_output(&self) -> DigitalState {
        self.output_state.clone()
    }
}
#[allow(unused)]
impl Digital1Line for XORElectric{}
#[allow(unused)]

impl XORElectric {
    ///This function stands for handling a Xor gate logic operation
    pub fn process(input_a: Option<Rc<dyn Digital1Line>>, input_b: Option<Rc<dyn Digital1Line>>) -> Rc<Self> {
        match (input_a, input_b) {
            (Some(a), Some(b)) => {
                let input_a_states = a.get_digital_output();
                let input_b_states = b.get_digital_output();
                let input_a_state = input_a_states.output_line_x(0);
                let input_b_state = input_b_states.output_line_x(0);
                let mut output_state = input_a_state
                    .clone()
                    .into_iter()
                    .zip(input_b_state.clone().into_iter())
                    .map(|(a_state, b_state)| Self::process_double_input(a_state, b_state))
                    .collect::<Vec<_>>();
                let loop_circuit = Self::handle_loop_circuit(output_state.clone());
                let output_states = DigitalState::new(vec![loop_circuit.clone()], 1, loop_circuit.len());
                let times = output_states.per_line_signals_count();
                Rc::new(XORElectric::new(
                    Some(a),
                    Some(b),
                    input_a_states,
                    input_b_states,
                    output_states,
                    times,
                ))
            }
            (Some(a), None) => {
                let input_b = None;
                let input_b_state = DigitalState::new(vec![vec![]], 1, 0);
                let input_a = Some(a.clone());
                let input_a_state = a.get_digital_output();
                let output_state = Self::process_single_input(input_a_state.clone());
                let times = output_state.per_line_signals_count();
                Rc::new(XORElectric::new(
                    input_a,
                    input_b,
                    input_a_state,
                    input_b_state,
                    output_state,
                    times,
                ))
            }
            (None, Some(b)) => {
                let input_a = None;
                let input_a_state = DigitalState::new(vec![vec![]], 1, 0);
                let input_b = Some(b.clone());
                let input_b_state = b.get_digital_output();
                let output_state = Self::process_single_input(input_b_state.clone());
                let times = output_state.per_line_signals_count();
                Rc::new(XORElectric::new(
                    input_a,
                    input_b,
                    input_a_state,
                    input_b_state,
                    output_state,
                    times,
                ))
            }
            (None, None) => {
                let output_state = DigitalState::new(vec![vec![]], 1, 0);
                let input_a = None;
                let input_a_state = DigitalState::new(vec![vec![]], 1, 0);
                let input_b = None;
                let input_b_state = DigitalState::new(vec![vec![]], 1, 0);
                Rc::new(XORElectric::new(
                    input_a,
                    input_b,
                    input_a_state,
                    input_b_state,
                    output_state,
                    0,
                ))
            }
        }
    }

    ///The purpose of this function is to deal with the situation of the loop circuit such as the stable output of the latch circuit.
    /// <div class="warning">
    ///
    ///crate will not give correct simulation results when simulating unstable circuits.
    ///Make sure you do not simulate unstable circuits.
    ///
    /// </div>
    fn handle_loop_circuit(mut output_state: Vec<Option<State>>) -> Vec<Option<State>> {
        let times = output_state.len();
        if output_state.len() > 1 {
            (1..times).into_iter().for_each(|t| {
                if output_state[t].clone().is_none() {
                    output_state[t] = output_state[t - 1].clone()
                }
            });
        };
        output_state
    }
    fn process_double_input(a_state: Option<State>, b_state: Option<State>) -> Option<State> {
        if let (Some(a), Some(b)) = (a_state.clone(), b_state.clone()) {
            if (a == ONE && b == ZERO) || (a == ZERO && b == ONE) {
                Some(ONE)
            } else {
                Some(ZERO)
            }
        } else {
            None
        }
    }

    fn process_single_input(input_state: DigitalState) -> DigitalState {
        let output_state = input_state
            .output_line_x(0)
            .into_iter()
            .map(|s| None)
            .collect::<Vec<_>>();
        DigitalState::new(vec![output_state.clone()], 1, output_state.len())
    }
}

impl XORElectric {
    pub fn new(
        input_a: Option<Rc<dyn Digital1Line>>,
        input_b: Option<Rc<dyn Digital1Line>>,
        input_a_state: DigitalState,
        input_b_state: DigitalState,
        output_state: DigitalState,
        times: usize,
    ) -> Self {
        Self {
            input_a,
            input_b,
            input_a_state,
            input_b_state,
            output_state,
            times,
        }
    }

    pub fn input_a(&self) -> Option<Rc<dyn Digital1Line>> {
        self.input_a.clone()
    }

    pub fn input_b(&self) -> Option<Rc<dyn Digital1Line>> {
        self.input_b.clone()
    }

    pub fn input_a_state(&self) -> DigitalState {
        self.input_a_state.clone()
    }

    pub fn input_b_state(&self) -> DigitalState {
        self.input_b_state.clone()
    }

    pub fn output_state(&self) -> DigitalState {
        self.output_state.clone()
    }

    pub fn times(&self) -> usize {
        self.times
    }
}
#[allow(unused)]
impl TwoInputDigital for XORElectric {
    fn set_input_a(&self, input_a: Option<Rc<dyn Digital1Line>>) -> Rc<Self> {
        Self::process(input_a, self.input_b.clone())
    }

    fn set_input_b(&self, input_b: Option<Rc<dyn Digital1Line>>) -> Rc<Self> {
        Self::process(self.input_a.clone(), input_b)
    }
}