use crate::id;
#[derive(Debug, Eq, PartialEq)]
pub struct SeenUnitNoVal {
pub id: id::NoVal,
pub count: u32,
}
#[derive(Debug, Eq, PartialEq)]
pub struct SeenUnitSingleVal {
pub id: id::SingleVal,
pub value: String,
}
#[derive(Debug, Eq, PartialEq)]
pub struct SeenUnitMultiVal {
pub id: id::MultiVal,
pub values: Vec<String>,
}
#[derive(Debug, Eq, PartialEq)]
pub enum SeenUnit {
No(SeenUnitNoVal),
Single(SeenUnitSingleVal),
Multi(SeenUnitMultiVal),
}
pub trait Getter {
type Ret;
fn match_and_cast<'a>(&self, h: &'a SeenUnit) -> Option<&'a Self::Ret>;
}
impl Getter for id::NoVal {
type Ret = SeenUnitNoVal;
fn match_and_cast<'a>(&self, h: &'a SeenUnit) -> Option<&'a Self::Ret> {
match h {
SeenUnit::No(h) if &h.id == self => Some(h),
_ => None,
}
}
}
impl Getter for id::SingleVal {
type Ret = SeenUnitSingleVal;
fn match_and_cast<'a>(&self, h: &'a SeenUnit) -> Option<&'a Self::Ret> {
match h {
SeenUnit::Single(h) if &h.id == self => Some(h),
_ => None,
}
}
}
impl Getter for id::MultiVal {
type Ret = SeenUnitMultiVal;
fn match_and_cast<'a>(&self, h: &'a SeenUnit) -> Option<&'a Self::Ret> {
match h {
SeenUnit::Multi(h) if &h.id == self => Some(h),
_ => None,
}
}
}
#[derive(Debug, Eq, PartialEq, Default)]
pub struct Seen(Vec<SeenUnit>);
impl Seen {
pub fn new() -> Self {
Default::default()
}
pub(crate) fn push_no_val(&mut self, id: id::NoVal) {
log::debug!("push no value {:?}", id);
for h in self.0.iter_mut() {
match h {
SeenUnit::No(h) if h.id == id => {
h.count += 1;
return;
}
_ => (),
}
}
self.0.push(SeenUnit::No(SeenUnitNoVal { id, count: 1 }));
}
pub(crate) fn push_single_val(&mut self, id: id::SingleVal, value: String) {
log::debug!("push single val {:?} {}", id, value);
for h in self.0.iter_mut() {
match h {
SeenUnit::Single(h) if h.id == id => {
log::info!(
"push single val {:?}: {} where old value exists: {}",
id,
value,
h.value
);
h.value = value;
return;
}
_ => (),
}
}
self.0
.push(SeenUnit::Single(SeenUnitSingleVal { id, value }));
}
pub(crate) fn push_multi_val(&mut self, id: id::MultiVal, value: String) {
log::debug!("push multi val {:?} {}", id, value);
for h in self.0.iter_mut() {
match h {
SeenUnit::Multi(h) if h.id == id => {
h.values.push(value);
return;
}
_ => (),
}
}
let values = vec![value];
self.0
.push(SeenUnit::Multi(SeenUnitMultiVal { id, values }));
}
pub(crate) fn push_valued(&mut self, id: id::Valued, value: String) {
match id {
id::Valued::Single(id) => self.push_single_val(id, value),
id::Valued::Multi(id) => self.push_multi_val(id, value),
}
}
pub fn find<I: Getter>(&self, id: I) -> Option<&I::Ret> {
for h in self.0.iter() {
let h = id.match_and_cast(h);
if h.is_some() {
return h;
}
}
None
}
#[doc(hidden)]
pub fn into_inner(self) -> Vec<SeenUnit> {
self.0
}
}