use std::{
collections::{btree_map, BTreeMap},
iter::IntoIterator,
ops::{AddAssign, Deref, DerefMut},
path::Path,
};
use rayon::prelude::*;
use crate::{
config::Config,
language::{Language, LanguageType},
utils,
};
#[derive(Debug, Default, PartialEq)]
pub struct Languages {
inner: BTreeMap<LanguageType, Language>,
}
impl serde::Serialize for Languages {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.inner.serialize(serializer)
}
}
impl<'de> serde::Deserialize<'de> for Languages {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let map = <_>::deserialize(deserializer)?;
Ok(Self::from_previous(map))
}
}
impl Languages {
fn from_previous(map: BTreeMap<LanguageType, Language>) -> Self {
use std::collections::btree_map::Entry;
let mut me = Self::new();
for (name, input_language) in map {
match me.entry(name) {
Entry::Occupied(mut entry) => {
*entry.get_mut() += input_language;
}
Entry::Vacant(entry) => {
entry.insert(input_language);
}
}
}
me
}
pub fn get_statistics<A: AsRef<Path>>(
&mut self,
paths: &[A],
ignored: &[&str],
config: &Config,
) {
utils::fs::get_all_files(paths, ignored, &mut self.inner, config);
self.inner.par_iter_mut().for_each(|(_, l)| l.total());
}
#[must_use]
pub fn new() -> Self {
Languages::default()
}
#[must_use]
pub fn total(self: &Languages) -> Language {
let mut total = Language::new();
for (ty, l) in self {
let language = l.summarise();
total.comments += language.comments;
total.blanks += language.blanks;
total.code += language.code;
total.inaccurate |= language.inaccurate;
total.children.insert(*ty, language.reports.clone());
}
total
}
}
impl IntoIterator for Languages {
type Item = <BTreeMap<LanguageType, Language> as IntoIterator>::Item;
type IntoIter = <BTreeMap<LanguageType, Language> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl<'a> IntoIterator for &'a Languages {
type Item = (&'a LanguageType, &'a Language);
type IntoIter = btree_map::Iter<'a, LanguageType, Language>;
fn into_iter(self) -> Self::IntoIter {
self.inner.iter()
}
}
impl<'a> IntoIterator for &'a mut Languages {
type Item = (&'a LanguageType, &'a mut Language);
type IntoIter = btree_map::IterMut<'a, LanguageType, Language>;
fn into_iter(self) -> Self::IntoIter {
self.inner.iter_mut()
}
}
impl AddAssign<BTreeMap<LanguageType, Language>> for Languages {
fn add_assign(&mut self, rhs: BTreeMap<LanguageType, Language>) {
for (name, language) in rhs {
if let Some(result) = self.inner.get_mut(&name) {
*result += language;
}
}
}
}
impl Deref for Languages {
type Target = BTreeMap<LanguageType, Language>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Languages {
fn deref_mut(&mut self) -> &mut BTreeMap<LanguageType, Language> {
&mut self.inner
}
}