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;

#[allow(unused)]
///AndElectric structure represent the AND logic circuit
/// ## EXAMPLE
///```rust
///    //create input sig1
/// use rust_play_digital::{AndElectric, Digital, Digital1Line, InitSig};
/// use rust_play_digital::State::{ONE, ZERO};
/// let  init_sig1 = InitSig::new(vec![Some(ZERO),Some(ONE),Some(ONE)]);
///    //create input sig2
/// let  init_sig2 = InitSig::new(vec![Some(ONE),Some(ZERO),Some(ONE)]);
///    // link sig1 to And logic circuit input a
///    // link sig2 to And logic circuit input b
/// let  and_electric = AndElectric::process(Some(init_sig1),Some(init_sig2));
///    //get And logic circuit output
/// println!("{:?}", and_electric.get_digital_output().outputs());
/// ```
pub struct AndElectric {
    input_a: Option<Rc<dyn Digital1Line>>,
    input_b: Option<Rc<dyn Digital1Line>>,
    input_a_states: DigitalState,
    input_b_states: DigitalState,
    output_states: DigitalState,
    times: usize,
}
#[allow(unused)]
impl Digital1Line for AndElectric{}
#[allow(unused)]
impl Digital for AndElectric {
    fn get_output(&self) -> DigitalState {
        self.output_states.clone()
    }
}
#[allow(unused)]
impl AndElectric {
    ///This function stands for handling a And 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.clone().get_digital_output();
                let input_b_states = b.clone().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 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 output_state = Self::handle_loop_circuit(output_state);
                let output_states =
                    DigitalState::new(vec![output_state.clone()], 1, output_state.len());
                let times = output_states.per_line_signals_count();
                Rc::new(AndElectric::new(
                    Some(a.clone()),
                    Some(b.clone()),
                    input_a_states,
                    input_b_states,
                    output_states,
                    times,
                ))
            }
            (Some(a), None) => {
                let input_b = None;
                let input_b_states = DigitalState::new(vec![vec![]], 1, 0);
                let input_a = Some(a.clone());
                let input_a_states = a.get_digital_output();
                let output_states = Self::process_single_input(input_a_states.clone());
                let times = input_a_states.per_line_signals_count();
                Rc::new(AndElectric::new(
                    input_a,
                    input_b,
                    input_a_states,
                    input_b_states,
                    output_states,
                    times,
                ))
            }
            (None, Some(b)) => {
                let input_a = None;
                let input_a_states = DigitalState::new(vec![vec![]], 1, 0);
                let input_b = Some(b.clone());
                let input_b_states = b.get_digital_output();
                let output_states = Self::process_single_input(input_b_states.clone());
                let times = output_states.per_line_signals_count();
                Rc::new(AndElectric::new(
                    input_a,
                    input_b,
                    input_a_states,
                    input_b_states,
                    output_states,
                    times,
                ))
            }
            (None, None) => {
                let output_states = DigitalState::new(vec![vec![]], 1, 0);
                let input_a = None;
                let input_a_states = DigitalState::new(vec![vec![]], 1, 0);
                let input_b = None;
                let input_b_states = DigitalState::new(vec![vec![]], 1, 0);
                Rc::new(AndElectric::new(
                    input_a,
                    input_b,
                    input_a_states,
                    input_b_states,
                    output_states,
                    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 == ONE {
                Some(ONE)
            } else {
                Some(ZERO)
            }
        } else if let (Some(a), None) = (a_state.clone(), b_state.clone()) {
            if a == ZERO { Some(ZERO) } else { None }
        } else if let (None, Some(b)) = (a_state.clone(), b_state.clone()) {
            if b == ZERO { Some(ZERO) } else { None }
        } else {
            None
        }
    }
    fn process_single_input(and_single_input: DigitalState) -> DigitalState {
        let digital_state = and_single_input
            .output_line_x(0)
            .into_iter()
            .map(|a_state| {
                if let Some(a) = a_state {
                    if a != ONE { Some(ZERO) } else { None }
                } else {
                    None
                }
            })
            .collect::<Vec<_>>();
        DigitalState::new(vec![digital_state.clone()], 1, digital_state.len())
    }
}
impl AndElectric {
    pub fn new(
        input_a: Option<Rc<dyn Digital1Line>>,
        input_b: Option<Rc<dyn Digital1Line>>,
        input_a_states: DigitalState,
        input_b_states: DigitalState,
        output_states: DigitalState,
        times: usize,
    ) -> Self {
        Self {
            input_a,
            input_b,
            input_a_states,
            input_b_states,
            output_states,
            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_states(&self) -> DigitalState {
        self.input_a_states.clone()
    }

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

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

    pub fn times(&self) -> usize {
        self.times
    }
}
#[allow(unused)]
impl TwoInputDigital for AndElectric {
    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)
    }
}