mod ascii;
mod bin;
mod conv_types;
mod dec;
mod hex;
mod octal;
use indexmap::{IndexMap, IndexSet};
use crate::Opts;
pub use conv_types::{InputConverterType, OutputConverterType};
type IntermediateValue = i128;
pub trait OutputConverter {
fn convert(&self, input: IntermediateValue) -> Result<String, ()>;
}
pub trait InputConverter {
fn convert(&self, input: &str) -> Result<IntermediateValue, ()>;
}
#[derive(Debug)]
pub struct ConversionOutput {
pub inner: IndexMap<InputConverterType, ConversionResult>,
}
impl ConversionOutput {
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
impl From<IndexMap<InputConverterType, ConversionResult>> for ConversionOutput {
fn from(value: IndexMap<InputConverterType, ConversionResult>) -> Self {
Self { inner: value }
}
}
impl FromIterator<(InputConverterType, ConversionResult)> for ConversionOutput {
fn from_iter<T: IntoIterator<Item = (InputConverterType, ConversionResult)>>(iter: T) -> Self {
let mut inner = IndexMap::new();
for (outconv, val) in iter {
inner.insert(outconv, val);
}
Self::from(inner)
}
}
#[derive(Debug)]
pub struct ConversionResult {
pub inner: IndexMap<OutputConverterType, String>,
}
impl ConversionResult {
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
impl From<IndexMap<OutputConverterType, String>> for ConversionResult {
fn from(value: IndexMap<OutputConverterType, String>) -> Self {
Self { inner: value }
}
}
impl FromIterator<(OutputConverterType, String)> for ConversionResult {
fn from_iter<T: IntoIterator<Item = (OutputConverterType, String)>>(iter: T) -> Self {
let mut inner = IndexMap::new();
for (outconv, val) in iter {
inner.insert(outconv, val);
}
Self::from(inner)
}
}
#[derive(Debug)]
pub enum ConversionError {
NoResults,
}
pub fn do_convert(opts: Opts) -> Result<ConversionOutput, ConversionError> {
let res: ConversionOutput = opts
.inconvs
.into_iter()
.filter_map(|inconv| {
if let Ok(int) = inconv.get_converter().convert(&opts.input) {
let res = proces_outconvs(&opts.outconvs, &inconv, int);
if res.is_empty() {
None
} else {
Some((inconv, res))
}
} else {
None
}
})
.collect();
if res.is_empty() {
Err(ConversionError::NoResults)
} else {
Ok(res)
}
}
pub fn proces_outconvs(
outconvs: &IndexSet<OutputConverterType>,
inconv: &InputConverterType,
input: IntermediateValue,
) -> ConversionResult {
outconvs
.into_iter()
.filter_map(|outconv| {
if inconv.is_outconv_excluded(outconv) {
return None;
}
if let Ok(out) = outconv.get_converter().convert(input) {
Some((outconv.clone(), out))
} else {
None
}
})
.collect()
}