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)]
pub struct OrElectric {
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 OrElectric{}
#[allow(unused)]
impl Digital for OrElectric {
fn get_output(&self) -> DigitalState {
self.output_states.clone()
}
}
impl OrElectric {
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 output_state = input_a_states
.output_line_x(0)
.clone()
.into_iter()
.zip(input_b_states.output_line_x(0).into_iter())
.map(|(a_state, b_state)| Self::process_double_input(a_state, b_state))
.collect::<Vec<Option<State>>>();
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(OrElectric::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_state = DigitalState::new(vec![vec![]], 0, 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(OrElectric::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(OrElectric::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(OrElectric::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 == ONE {
Some(ONE)
} else {
Some(ZERO)
}
} else if let (Some(a), None) = (a_state.clone(), b_state.clone()) {
if a == ONE { Some(ONE) } else { None }
} else if let (None, Some(b)) = (a_state.clone(), b_state.clone()) {
if b == ONE { Some(ONE) } else { None }
} else {
None
}
}
fn process_single_input(input_state: DigitalState) -> DigitalState {
let s = input_state
.output_line_x(0)
.into_iter()
.map(|a_state| {
if let Some(a) = a_state {
if a == ONE { Some(ONE) } else { None }
} else {
None
}
})
.collect::<Vec<_>>();
DigitalState::new(vec![s.clone()], 1, s.len())
}
}
impl OrElectric {
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 OrElectric {
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)
}
}