use crate::common::{Digital, TwoInputDigital};
use crate::output::State::{ONE, ZERO};
use crate::output::{DigitalState, State};
use std::rc::Rc;
use crate::Digital1Line;
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 {
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,
))
}
}
}
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)
}
}