mirror of
https://github.com/XAMPPRocky/tokei
synced 2024-10-05 23:39:28 +00:00
first attempt at moving stuff around
This commit is contained in:
parent
5ecad644f4
commit
76be54b67d
38
Cargo.lock
generated
38
Cargo.lock
generated
|
@ -9,10 +9,10 @@ dependencies = [
|
|||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_cbor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_codegen 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_yaml 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -24,10 +24,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "aster"
|
||||
version = "0.16.0"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -133,20 +133,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quasi"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quasi_codegen"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aster 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -188,14 +188,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_codegen"
|
||||
version = "0.7.5"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aster 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quasi 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quasi_codegen 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quasi 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quasi_codegen 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -223,15 +223,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "syntex"
|
||||
version = "0.32.0"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntex_syntax"
|
||||
version = "0.32.0"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -22,8 +22,8 @@ path = "src/main.rs"
|
|||
|
||||
# For building serde in stable.
|
||||
[build-dependencies]
|
||||
serde_codegen = "0.7.5"
|
||||
syntex = "0.32.0"
|
||||
serde_codegen = "0.7.7"
|
||||
syntex = "0.33.0"
|
||||
|
||||
# Dependencies, and why they are used.
|
||||
# - Clap: For CLI argument parsing.
|
||||
|
|
150
src/language/language.rs
Normal file
150
src/language/language.rs
Normal file
|
@ -0,0 +1,150 @@
|
|||
use std::path::PathBuf;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use utils::*;
|
||||
use stats::Stats;
|
||||
use super::LanguageName;
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct LanguageStatistics {
|
||||
pub blanks: usize,
|
||||
pub code: usize,
|
||||
pub comments: usize,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub files: Vec<PathBuf>,
|
||||
pub stats: Vec<Stats>,
|
||||
pub lines: usize,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub line_comment: Vec<&'static str>,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub multi_line: Vec<(&'static str, &'static str)>,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub nested: bool,
|
||||
pub total_files: usize,
|
||||
}
|
||||
|
||||
impl LanguageStatistics {
|
||||
pub fn new(line_comment: Vec<&'static str>,
|
||||
multi_line: Vec<(&'static str, &'static str)>)
|
||||
-> Self {
|
||||
|
||||
LanguageStatistics {
|
||||
line_comment: line_comment,
|
||||
multi_line: multi_line,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nested(mut self) -> Self {
|
||||
self.nested = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn new_c() -> Self {
|
||||
LanguageStatistics {
|
||||
line_comment: vec!["//"],
|
||||
multi_line: vec![("/*", "*/")],
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_html() -> Self {
|
||||
LanguageStatistics { multi_line: vec![("<!--", "-->")], ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn new_blank() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn new_func() -> Self {
|
||||
LanguageStatistics { multi_line: vec![("(*", "*)")], ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn new_hash() -> Self {
|
||||
Self::new_single(vec!["#"])
|
||||
}
|
||||
|
||||
pub fn new_multi(multi_line: Vec<(&'static str, &'static str)>) -> Self {
|
||||
LanguageStatistics { multi_line: multi_line, ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn new_pro() -> Self {
|
||||
LanguageStatistics {
|
||||
line_comment: vec!["%"],
|
||||
multi_line: vec![("/*", "*/")],
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_single(line_comment: Vec<&'static str>) -> Self {
|
||||
LanguageStatistics { line_comment: line_comment, ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.code == 0 && self.comments == 0 && self.blanks == 0 && self.lines == 0
|
||||
}
|
||||
|
||||
pub fn is_blank(&self) -> bool {
|
||||
self.line_comment.is_empty() && self.multi_line.is_empty()
|
||||
}
|
||||
|
||||
pub fn sort_by(&mut self, category: &str) {
|
||||
match category {
|
||||
BLANKS => self.stats.sort_by(|a, b| b.blanks.cmp(&a.blanks)),
|
||||
COMMENTS => self.stats.sort_by(|a, b| b.comments.cmp(&a.comments)),
|
||||
CODE => self.stats.sort_by(|a, b| b.code.cmp(&a.code)),
|
||||
TOTAL => self.stats.sort_by(|a, b| b.lines.cmp(&a.lines)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(&self, name: LanguageName) {
|
||||
println!(" {: <18} {: >6} {:>12} {:>12} {:>12} {:>12}",
|
||||
name.name(),
|
||||
self.total_files,
|
||||
self.lines,
|
||||
self.code,
|
||||
self.comments,
|
||||
self.blanks)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for LanguageStatistics {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.total_files += rhs.total_files;
|
||||
self.lines += rhs.lines;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.code += rhs.code;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AddAssign<&'a LanguageStatistics> for LanguageStatistics {
|
||||
fn add_assign(&mut self, rhs: &'a Self) {
|
||||
self.total_files += rhs.total_files;
|
||||
self.lines += rhs.lines;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.code += rhs.code;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AddAssign<&'a mut LanguageStatistics> for LanguageStatistics {
|
||||
fn add_assign(&mut self, rhs: &mut Self) {
|
||||
self.total_files += rhs.total_files;
|
||||
self.lines += rhs.lines;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.code += rhs.code;
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Stats> for LanguageStatistics {
|
||||
fn add_assign(&mut self, rhs: Stats) {
|
||||
self.lines += rhs.lines;
|
||||
self.code += rhs.code;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.stats.push(rhs);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt;
|
||||
use std::path::Path;
|
||||
|
||||
use utils::fs::*;
|
||||
use utils::*;
|
||||
use self::LanguageName::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
use super::{Language, LanguageName};
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::btree_map;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
use serde_cbor;
|
||||
use serde_json;
|
||||
use serde_yaml;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use utils::*;
|
||||
use super::{Language, LanguageName};
|
||||
use super::LanguageName::*;
|
||||
use self::LanguageError::*;
|
||||
use stats::Stats;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Languages {
|
||||
|
@ -8,34 +24,65 @@ pub struct Languages {
|
|||
|
||||
|
||||
impl Languages {
|
||||
pub fn convert_input(contents: String) -> Option<BTreeMap<String, Language>> {
|
||||
if contents.is_empty() {
|
||||
None
|
||||
} else if let Ok(result) = serde_json::from_str(&*contents) {
|
||||
Some(result)
|
||||
} else if let Ok(result) = serde_yaml::from_str(&*contents) {
|
||||
Some(result)
|
||||
} else if let Ok(result) = serde_cbor::from_slice(&*contents.from_hex().unwrap()) {
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
pub fn from_previous(previous: String) -> Result<Self, LanguageError> {
|
||||
let mut _self = Self::new();
|
||||
let map: Result<BTreeMap<LanguageName, Language>, LanguageError> = {
|
||||
if previous.is_empty() {
|
||||
Err(SerdeEmpty)
|
||||
} else if let Ok(result) = serde_json::from_str(&*previous) {
|
||||
Ok(result)
|
||||
} else if let Ok(result) = serde_yaml::from_str(&*previous) {
|
||||
Ok(result)
|
||||
} else if let Ok(result) = serde_cbor::from_slice(&*previous.from_hex().unwrap()) {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(InvalidFormat)
|
||||
}
|
||||
};
|
||||
|
||||
match map {
|
||||
Ok(map) => {
|
||||
for (name, input_language) in map {
|
||||
if let Some(language) = _self.get_mut(&LanguageName::from(name)) {
|
||||
*language += input_language;
|
||||
}
|
||||
}
|
||||
Ok(_self)
|
||||
}
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_statistics<I, P>(paths: P, ignored: P)
|
||||
where I: Iterator<Item = &str>,
|
||||
P: Into<Cow<'a, I>>
|
||||
pub fn add_previous(&mut self, previous: String) -> Result<(), LanguageError> {
|
||||
let previous_languages = match Self::from_previous(previous) {
|
||||
Ok(result) => result,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
for (key, previous) in previous_languages {
|
||||
if let Some(language) = self.get_mut(&key) {
|
||||
*language += previous;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_statistics<'a, I, C>(&mut self, paths: C, ignored: C)
|
||||
where I: 'a + Iterator<Item = &'a str> + Clone,
|
||||
C: Into<Cow<'a, I>>
|
||||
{
|
||||
|
||||
get_all_files(paths.into(), ignored_directories.into(), &mut self.inner);
|
||||
get_all_files(paths.into(), ignored.into(), &mut self.inner);
|
||||
|
||||
self.inner.par_iter_mut().for_each(|&mut (name, ref mut language)| {
|
||||
let mut language_iter: Vec<_> = self.inner.iter_mut().collect();
|
||||
|
||||
language_iter.par_iter_mut().for_each(|&mut (name, ref mut language)| {
|
||||
if language.files.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
language.total_files = language.files.len();
|
||||
let is_fortran = name == FortranModern || name == FortranLegacy;
|
||||
let is_fortran = name == &FortranModern || name == &FortranLegacy;
|
||||
|
||||
let files: Vec<_> = language.files.drain(..).collect();
|
||||
for file in files {
|
||||
|
@ -46,12 +93,12 @@ impl Languages {
|
|||
|
||||
let contents = {
|
||||
let mut contents = String::new();
|
||||
let _ = rs_or_cont!(rs_or_cont!(File::open(file)).read_to_string(&mut contents));
|
||||
let _ = rs_or_cont!(rs_or_cont!(File::open(file))
|
||||
.read_to_string(&mut contents));
|
||||
contents
|
||||
};
|
||||
|
||||
let lines = contents.lines();
|
||||
stats.lines += lines.size_hint().0;
|
||||
|
||||
if language.is_blank() {
|
||||
stats.code += lines.count();
|
||||
|
@ -59,8 +106,11 @@ impl Languages {
|
|||
}
|
||||
|
||||
'line: for line in lines {
|
||||
// FORTRAN has a rule where it only counts as a comment if it's the first character
|
||||
// in the column, so removing starting whitespace could cause a miscount.
|
||||
stats.lines += 1;
|
||||
|
||||
// FORTRAN has a rule where it only counts as a comment if it's the first
|
||||
// character in the column, so removing starting whitespace could cause a
|
||||
// miscount.
|
||||
let line = if is_fortran {
|
||||
line
|
||||
} else {
|
||||
|
@ -74,7 +124,10 @@ impl Languages {
|
|||
|
||||
for &(multi_line, multi_line_end) in &language.multi_line {
|
||||
if line.starts_with(multi_line) ||
|
||||
has_trailing_comments(line, multi_line, multi_line_end, language.nested) {
|
||||
has_trailing_comments(line,
|
||||
multi_line,
|
||||
multi_line_end,
|
||||
language.nested) {
|
||||
previous_comment_start = multi_line;
|
||||
is_in_comments = true;
|
||||
if language.nested {
|
||||
|
@ -86,7 +139,8 @@ impl Languages {
|
|||
|
||||
if is_in_comments {
|
||||
for &(multi_line, multi_line_end) in &language.multi_line {
|
||||
if multi_line == previous_comment_start && line.contains(multi_line_end) {
|
||||
if multi_line == previous_comment_start &&
|
||||
line.contains(multi_line_end) {
|
||||
if language.nested {
|
||||
comment_depth -= 1;
|
||||
if comment_depth == 0 {
|
||||
|
@ -110,12 +164,17 @@ impl Languages {
|
|||
stats.code += 1;
|
||||
}
|
||||
|
||||
*language += stats;
|
||||
**language += stats;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, key: &LanguageName) -> Option<&mut Language> {
|
||||
self.inner.get_mut(key)
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
use super::LanguageName::*;
|
||||
let map = btreemap! {
|
||||
ActionScript => Language::new_c(),
|
||||
Assembly => Language::new_single(vec![";"]),
|
||||
|
@ -194,4 +253,48 @@ impl Languages {
|
|||
|
||||
Languages { inner: map }
|
||||
}
|
||||
|
||||
pub fn to_cbor(&self) -> Result<Vec<u8>, serde_cbor::Error> {
|
||||
serde_cbor::to_vec(&self.inner)
|
||||
}
|
||||
pub fn to_json(&self) -> Result<String, serde_json::Error> {
|
||||
serde_json::to_string(&self.inner)
|
||||
}
|
||||
pub fn to_yaml(&self) -> Result<String, serde_yaml::Error> {
|
||||
serde_yaml::to_string(&self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl IntoIterator for Languages {
|
||||
type Item = <BTreeMap<LanguageName, Language> as IntoIterator>::Item;
|
||||
type IntoIter = <BTreeMap<LanguageName, Language> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.inner.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Languages {
|
||||
type Item = (&'a LanguageName, &'a Language);
|
||||
type IntoIter = btree_map::Iter<'a, LanguageName, Language>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.inner.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Languages {
|
||||
type Item = (&'a LanguageName, &'a mut Language);
|
||||
type IntoIter = btree_map::IterMut<'a, LanguageName, Language>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.inner.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LanguageError {
|
||||
SerdeEmpty,
|
||||
InvalidFormat,
|
||||
}
|
||||
|
|
|
@ -2,157 +2,10 @@
|
|||
// Use of this source code is governed by the MIT/APACHE2.0 license that can be
|
||||
// found in the LICENCE-{APACHE - MIT} file.
|
||||
|
||||
mod language_name;
|
||||
pub mod language;
|
||||
pub mod languages;
|
||||
pub mod language_name;
|
||||
|
||||
pub use language_name::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use consts::*;
|
||||
use language_name::LanguageName;
|
||||
use stats::Stats;
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct Language {
|
||||
pub blanks: usize,
|
||||
pub code: usize,
|
||||
pub comments: usize,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub files: Vec<PathBuf>,
|
||||
pub stats: Vec<Stats>,
|
||||
pub lines: usize,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub line_comment: Vec<&'static str>,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub multi_line: Vec<(&'static str, &'static str)>,
|
||||
#[serde(skip_deserializing, skip_serializing)]
|
||||
pub nested: bool,
|
||||
pub total_files: usize,
|
||||
}
|
||||
|
||||
impl Language {
|
||||
pub fn new(line_comment: Vec<&'static str>,
|
||||
multi_line: Vec<(&'static str, &'static str)>)
|
||||
-> Self {
|
||||
|
||||
Language {
|
||||
line_comment: line_comment,
|
||||
multi_line: multi_line,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nested(mut self) -> Self {
|
||||
self.nested = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn new_c() -> Self {
|
||||
Language {
|
||||
line_comment: vec!["//"],
|
||||
multi_line: vec![("/*", "*/")],
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_html() -> Self {
|
||||
Language { multi_line: vec![("<!--", "-->")], ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn new_blank() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn new_func() -> Self {
|
||||
Language { multi_line: vec![("(*", "*)")], ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn new_hash() -> Self {
|
||||
Self::new_single(vec!["#"])
|
||||
}
|
||||
|
||||
pub fn new_multi(multi_line: Vec<(&'static str, &'static str)>) -> Self {
|
||||
Language { multi_line: multi_line, ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn new_pro() -> Self {
|
||||
Language {
|
||||
line_comment: vec!["%"],
|
||||
multi_line: vec![("/*", "*/")],
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_single(line_comment: Vec<&'static str>) -> Self {
|
||||
Language { line_comment: line_comment, ..Self::default() }
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.code == 0 && self.comments == 0 && self.blanks == 0 && self.lines == 0
|
||||
}
|
||||
|
||||
pub fn is_blank(&self) -> bool {
|
||||
self.line_comment.is_empty() && self.multi_line.is_empty()
|
||||
}
|
||||
|
||||
pub fn sort_by(&mut self, category: &str) {
|
||||
match category {
|
||||
BLANKS => self.stats.sort_by(|a, b| b.blanks.cmp(&a.blanks)),
|
||||
COMMENTS => self.stats.sort_by(|a, b| b.comments.cmp(&a.comments)),
|
||||
CODE => self.stats.sort_by(|a, b| b.code.cmp(&a.code)),
|
||||
TOTAL => self.stats.sort_by(|a, b| b.lines.cmp(&a.lines)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(&self, name: LanguageName) {
|
||||
println!(" {: <18} {: >6} {:>12} {:>12} {:>12} {:>12}",
|
||||
name.name(),
|
||||
self.total_files,
|
||||
self.lines,
|
||||
self.code,
|
||||
self.comments,
|
||||
self.blanks)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Language {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.total_files += rhs.total_files;
|
||||
self.lines += rhs.lines;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.code += rhs.code;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AddAssign<&'a Language> for Language {
|
||||
fn add_assign(&mut self, rhs: &'a Self) {
|
||||
self.total_files += rhs.total_files;
|
||||
self.lines += rhs.lines;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.code += rhs.code;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AddAssign<&'a mut Language> for Language {
|
||||
fn add_assign(&mut self, rhs: &mut Self) {
|
||||
self.total_files += rhs.total_files;
|
||||
self.lines += rhs.lines;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.code += rhs.code;
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Stats> for Language {
|
||||
fn add_assign(&mut self, rhs: Stats) {
|
||||
self.lines += rhs.lines;
|
||||
self.code += rhs.code;
|
||||
self.comments += rhs.comments;
|
||||
self.blanks += rhs.blanks;
|
||||
self.stats.push(rhs);
|
||||
}
|
||||
}
|
||||
pub use self::languages::Languages;
|
||||
pub use self::language::LanguageStatistics;
|
||||
pub use self::language_name::*;
|
||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -1,2 +1,13 @@
|
|||
#[macro_use]
|
||||
extern crate maplit;
|
||||
extern crate glob;
|
||||
extern crate rayon;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde;
|
||||
extern crate serde_cbor;
|
||||
extern crate serde_json;
|
||||
extern crate serde_yaml;
|
||||
extern crate toml;
|
||||
extern crate walkdir;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
|
||||
|
|
|
@ -1,18 +1,6 @@
|
|||
extern crate glob;
|
||||
#[macro_use]
|
||||
extern crate maplit;
|
||||
extern crate rayon;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde;
|
||||
extern crate serde_cbor;
|
||||
extern crate serde_json;
|
||||
extern crate serde_yaml;
|
||||
extern crate toml;
|
||||
extern crate walkdir;
|
||||
|
||||
#[macro_use]
|
||||
mod utils;
|
||||
mod language;
|
||||
mod stats;
|
||||
pub mod language;
|
||||
pub mod stats;
|
||||
|
||||
pub use language::Languages;
|
||||
pub use language::*;
|
||||
|
|
207
src/main.rs
207
src/main.rs
|
@ -1,3 +1,208 @@
|
|||
// Copyright (c) 2015 Aaron Power
|
||||
// Use of this source code is governed by the MIT/APACHE2.0 license that can be
|
||||
// found in the LICENCE-{APACHE, MIT} file.
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate tokei;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/main.rs"));
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use clap::App;
|
||||
|
||||
use tokei::language::{Language, Languages};
|
||||
|
||||
pub const ROW: &'static str = "-------------------------------------------------------------------------------";
|
||||
pub const FILES: &'static str = "files";
|
||||
|
||||
fn main() {
|
||||
// Get options at the beginning, so the program doesn't have to make any extra calls to get the
|
||||
// information, and there isn't any magic strings.
|
||||
let yaml = load_yaml!("../cli.yml");
|
||||
let matches = App::from_yaml(yaml).get_matches();
|
||||
let files_option = matches.is_present(FILES);
|
||||
let input_option = matches.value_of("file_input");
|
||||
let output_option = matches.value_of("output");
|
||||
let language_option = matches.is_present("languages");
|
||||
let sort_option = matches.value_of("sort");
|
||||
let paths = matches.values_of("input").unwrap();
|
||||
let ignored_directories = {
|
||||
let mut ignored_directories = vec![".git"];
|
||||
if let Some(user_ignored) = matches.values_of("exclude") {
|
||||
for ignored in user_ignored {
|
||||
ignored_directories.push(ignored);
|
||||
}
|
||||
}
|
||||
ignored_directories
|
||||
};
|
||||
|
||||
let languages = Languages::new();
|
||||
|
||||
if language_option {
|
||||
for key in languages.keys() {
|
||||
println!("{:<25}", key);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(input) = input_option {
|
||||
match File::open(input) {
|
||||
Ok(mut file) => {
|
||||
let contents = {
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).unwrap();
|
||||
contents
|
||||
};
|
||||
|
||||
language.add_previous(contents)
|
||||
}
|
||||
Err(_) => {
|
||||
if input == "stdin" {
|
||||
let mut stdin = std::io::stdin();
|
||||
let mut buffer = String::new();
|
||||
|
||||
let _ = stdin.read_to_string(&mut buffer);
|
||||
language.add_previous(buffer)
|
||||
} else {
|
||||
language.add_previous(String::from(input))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if output_option == None {
|
||||
println!("{}", ROW);
|
||||
println!(" {:<12} {:>12} {:>12} {:>12} {:>12} {:>12}",
|
||||
"Language",
|
||||
"Files",
|
||||
"Lines",
|
||||
"Code",
|
||||
"Comments",
|
||||
"Blanks");
|
||||
println!("{}", ROW);
|
||||
}
|
||||
|
||||
let mut total = LanguageStatistics::new_blank();
|
||||
|
||||
let print_animation = output_option == None;
|
||||
let (tx, rx) = channel();
|
||||
let child = thread::spawn(move || {
|
||||
loop {
|
||||
if let Ok(_) = rx.try_recv() {
|
||||
break;
|
||||
}
|
||||
|
||||
if print_animation {
|
||||
print!(" Counting files. \r");
|
||||
thread::sleep(Duration::from_millis(4));
|
||||
print!(" Counting files..\r");
|
||||
thread::sleep(Duration::from_millis(4));
|
||||
print!(" Counting files...\r");
|
||||
thread::sleep(Duration::from_millis(4));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
languages.get_statistics(paths, ignored_directories);
|
||||
|
||||
if output_option == None {
|
||||
print!("{}", CLEAR);
|
||||
}
|
||||
|
||||
for language in &languages {
|
||||
if !language.is_empty() {
|
||||
if sort_option == None && output_option == None {
|
||||
if files_option {
|
||||
language.print(name);
|
||||
println!("{}", ROW);
|
||||
|
||||
for stat in &language.stats {
|
||||
println!("{}", stat);
|
||||
}
|
||||
println!("{}", ROW);
|
||||
} else if output_option == None {
|
||||
language.print(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = tx.send(());
|
||||
let _ = child.join();
|
||||
|
||||
for &(_, ref language) in &languages {
|
||||
if !language.is_empty() {
|
||||
total += language;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(format) = output_option {
|
||||
match &*format {
|
||||
"cbor" => {
|
||||
let cbor: Vec<_> = languages.to_cbor().unwrap();
|
||||
|
||||
for byte in cbor {
|
||||
print!("{:02x}", byte);
|
||||
}
|
||||
}
|
||||
"json" => print!("{}", languages.to_json().unwrap()),
|
||||
// "toml" => print!("{}", {
|
||||
// let encoder = toml::Encoder::new();
|
||||
// lang_map.encode(&mut encoder).unwrap();
|
||||
// encoder.toml
|
||||
// }),
|
||||
"yaml" => print!("{}", languages.to_yaml().unwrap()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else if let Some(sort_category) = sort_option {
|
||||
|
||||
for &mut (_, ref mut language) in &mut languages {
|
||||
match &*sort_category {
|
||||
BLANKS => language.sort_by(BLANKS),
|
||||
COMMENTS => language.sort_by(COMMENTS),
|
||||
CODE => language.sort_by(CODE),
|
||||
FILES => {}
|
||||
TOTAL => language.sort_by(TOTAL),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
let languages: Vec<_> = languages.into_iter().collect();
|
||||
|
||||
match &*sort_category {
|
||||
BLANKS => languages.sort_by(|a, b| b.1.blanks.cmp(&a.1.blanks)),
|
||||
COMMENTS => languages.sort_by(|a, b| b.1.comments.cmp(&a.1.comments)),
|
||||
CODE => languages.sort_by(|a, b| b.1.code.cmp(&a.1.code)),
|
||||
FILES => languages.sort_by(|a, b| b.1.files.len().cmp(&a.1.files.len())),
|
||||
TOTAL => languages.sort_by(|a, b| b.1.lines.cmp(&a.1.lines)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
for (name, language) in languages {
|
||||
if !language.is_empty() {
|
||||
if !files_option {
|
||||
language.print(name);
|
||||
} else {
|
||||
language.print(name);
|
||||
println!("{}", ROW);
|
||||
for file in &language.stats {
|
||||
println!("{}", file);
|
||||
}
|
||||
println!("{}", ROW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if output_option == None {
|
||||
if !files_option {
|
||||
println!("{}", ROW);
|
||||
}
|
||||
total.print(__Total);
|
||||
println!("{}", ROW);
|
||||
}
|
||||
}
|
||||
|
|
226
src/main.rs.in
226
src/main.rs.in
|
@ -1,226 +0,0 @@
|
|||
// Copyright (c) 2015 Aaron Power
|
||||
// Use of this source code is governed by the MIT/APACHE2.0 license that can be
|
||||
// found in the LICENCE-{APACHE, MIT} file.
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate tokei;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use clap::App;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use consts::*;
|
||||
use fsutil::*;
|
||||
use language::Language;
|
||||
use language_name::LanguageName;
|
||||
use language_name::LanguageName::*;
|
||||
use stats::Stats;
|
||||
|
||||
fn main() {
|
||||
// Get options at the beginning, so the program doesn't have to make any extra calls to get the
|
||||
// information, and there isn't any magic strings.
|
||||
let yaml = load_yaml!("../cli.yml");
|
||||
let matches = App::from_yaml(yaml).get_matches();
|
||||
let files_option = matches.is_present(FILES);
|
||||
let input_option = matches.value_of("file_input");
|
||||
let output_option = matches.value_of("output");
|
||||
let language_option = matches.is_present("languages");
|
||||
let sort_option = matches.value_of("sort");
|
||||
let paths = matches.values_of("input").unwrap();
|
||||
let ignored_directories = {
|
||||
let mut ignored_directories = vec![".git"];
|
||||
if let Some(user_ignored) = matches.values_of("exclude") {
|
||||
for ignored in user_ignored {
|
||||
ignored_directories.push(ignored);
|
||||
}
|
||||
}
|
||||
ignored_directories
|
||||
};
|
||||
|
||||
|
||||
|
||||
if language_option {
|
||||
for key in languages.keys() {
|
||||
println!("{:<25}", key);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(input) = input_option {
|
||||
let deserded_map = match File::open(input) {
|
||||
Ok(mut file) => {
|
||||
let contents = {
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).unwrap();
|
||||
contents
|
||||
};
|
||||
|
||||
convert_input(contents)
|
||||
}
|
||||
Err(_) => {
|
||||
if input == "stdin" {
|
||||
let mut stdin = std::io::stdin();
|
||||
let mut buffer = String::new();
|
||||
|
||||
let _ = stdin.read_to_string(&mut buffer);
|
||||
convert_input(buffer)
|
||||
} else {
|
||||
convert_input(String::from(input))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(deserded_map) = deserded_map {
|
||||
for (name, input_language) in deserded_map {
|
||||
if let Some(language) = languages.get_mut(&LanguageName::from(name)) {
|
||||
*language += input_language;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("Input provided wasn't a path, or valid CBOR, JSON, or YAML.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if output_option == None {
|
||||
println!("{}", ROW);
|
||||
println!(" {:<12} {:>12} {:>12} {:>12} {:>12} {:>12}",
|
||||
"Language",
|
||||
"Files",
|
||||
"Lines",
|
||||
"Code",
|
||||
"Comments",
|
||||
"Blanks");
|
||||
println!("{}", ROW);
|
||||
}
|
||||
|
||||
let mut total = Language::new_blank();
|
||||
|
||||
let print_animation = output_option == None;
|
||||
let (tx, rx) = channel();
|
||||
let child = thread::spawn(move || {
|
||||
loop {
|
||||
if let Ok(_) = rx.try_recv() {
|
||||
break;
|
||||
}
|
||||
|
||||
if print_animation {
|
||||
print!("\x1B[?25l");
|
||||
print!(" Counting files. \r");
|
||||
thread::sleep(Duration::from_millis(4));
|
||||
print!(" Counting files..\r");
|
||||
thread::sleep(Duration::from_millis(4));
|
||||
print!(" Counting files...\r");
|
||||
thread::sleep(Duration::from_millis(4));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// if output_option == None {
|
||||
// print!("{}", CLEAR);
|
||||
// }
|
||||
|
||||
// if !language.is_empty() {
|
||||
// if sort_option == None && output_option == None {
|
||||
// if files_option {
|
||||
// language.print(name);
|
||||
// println!("{}", ROW);
|
||||
|
||||
// for stat in &language.stats {
|
||||
// println!("{}", stat);
|
||||
// }
|
||||
// println!("{}", ROW);
|
||||
// } else if output_option == None {
|
||||
// language.print(name);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
let _ = tx.send(());
|
||||
let _ = child.join();
|
||||
|
||||
for &(_, ref language) in &languages {
|
||||
if !language.is_empty() {
|
||||
total += language;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(format) = output_option {
|
||||
|
||||
let mut lang_map = BTreeMap::new();
|
||||
|
||||
for (key, value) in languages {
|
||||
if !value.is_empty() {
|
||||
lang_map.insert(format!("{:?}", key), value);
|
||||
}
|
||||
}
|
||||
|
||||
match &*format {
|
||||
"cbor" => {
|
||||
let cbor: Vec<_> = serde_cbor::to_vec(&lang_map).unwrap();
|
||||
|
||||
for byte in cbor {
|
||||
print!("{:02x}", byte);
|
||||
}
|
||||
}
|
||||
"json" => print!("{}", serde_json::to_string(&lang_map).unwrap()),
|
||||
"toml" => print!("{}", {
|
||||
let encoder = toml::Encoder::new();
|
||||
lang_map.encode(&mut encoder).unwrap();
|
||||
encoder.toml
|
||||
}),
|
||||
"yaml" => print!("{}", serde_yaml::to_string(&lang_map).unwrap()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else if let Some(sort_category) = sort_option {
|
||||
|
||||
for &mut (_, ref mut language) in &mut languages {
|
||||
match &*sort_category {
|
||||
BLANKS => language.sort_by(BLANKS),
|
||||
COMMENTS => language.sort_by(COMMENTS),
|
||||
CODE => language.sort_by(CODE),
|
||||
FILES => {}
|
||||
TOTAL => language.sort_by(TOTAL),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
match &*sort_category {
|
||||
BLANKS => languages.sort_by(|a, b| b.1.blanks.cmp(&a.1.blanks)),
|
||||
COMMENTS => languages.sort_by(|a, b| b.1.comments.cmp(&a.1.comments)),
|
||||
CODE => languages.sort_by(|a, b| b.1.code.cmp(&a.1.code)),
|
||||
FILES => languages.sort_by(|a, b| b.1.files.len().cmp(&a.1.files.len())),
|
||||
TOTAL => languages.sort_by(|a, b| b.1.lines.cmp(&a.1.lines)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
for (name, language) in languages {
|
||||
if !language.is_empty() {
|
||||
if !files_option {
|
||||
language.print(name);
|
||||
} else {
|
||||
language.print(name);
|
||||
println!("{}", ROW);
|
||||
for file in &language.stats {
|
||||
println!("{}", file);
|
||||
}
|
||||
println!("{}", ROW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if output_option == None {
|
||||
if !files_option {
|
||||
println!("{}", ROW);
|
||||
}
|
||||
total.print(__Total);
|
||||
println!("{}", ROW);
|
||||
print!("\x1B[?25h\r");
|
||||
}
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
pub const CLEAR: &'static str = " \r";
|
||||
pub const ROW: &'static str = "-------------------------------------------------------------------------------";
|
||||
pub const BLANKS: &'static str = "blanks";
|
||||
pub const COMMENTS: &'static str = "comments";
|
||||
pub const CODE: &'static str = "code";
|
||||
pub const FILES: &'static str = "files";
|
||||
pub const TOTAL: &'static str = "total";
|
||||
|
|
|
@ -2,16 +2,13 @@
|
|||
// Use of this source code is governed by the APACHE2.0/MIT licence that can be
|
||||
// found in the LICENCE-{APACHE/MIT} file.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use glob::glob;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use serde_cbor;
|
||||
use serde_json;
|
||||
use serde_yaml;
|
||||
use walkdir::{WalkDir, WalkDirIterator};
|
||||
|
||||
use language::{Language, LanguageName};
|
||||
|
@ -52,17 +49,26 @@ pub fn has_trailing_comments(line: &str,
|
|||
in_comments != 0
|
||||
}
|
||||
|
||||
pub fn get_all_files<'a, I: Iterator<Item = &'a str>>(paths: I,
|
||||
ignored_directories: Vec<&str>,
|
||||
languages: &mut BTreeMap<LanguageName,
|
||||
Language>) {
|
||||
pub fn get_all_files<'a, I>(mut paths: Cow<'a, I>,
|
||||
mut ignored_directories: Cow<'a, I>,
|
||||
languages: &mut BTreeMap<LanguageName, Language>)
|
||||
where I: Iterator<Item = &'a str> + Clone + 'a
|
||||
{
|
||||
let paths = paths.to_mut();
|
||||
let ignored_directories = ignored_directories.to_mut();
|
||||
for path in paths {
|
||||
// A small metadata check to check if the file actually exists, this is used over calling
|
||||
// File::open because we're going to be passing the path to either glob() or WalkDir::new()
|
||||
if let Err(_) = Path::new(path).metadata() {
|
||||
if let Ok(paths) = glob(path) {
|
||||
for path in paths {
|
||||
'path: for path in paths {
|
||||
let path = rs_or_cont!(path);
|
||||
|
||||
for ig in ignored_directories.clone() {
|
||||
if opt_or_cont!(path.to_str()).contains(ig) {
|
||||
continue 'path;
|
||||
}
|
||||
}
|
||||
let mut language = if opt_or_cont!(path.to_str()).contains("Makefile") {
|
||||
languages.get_mut(&Makefile).unwrap()
|
||||
} else {
|
||||
|
@ -74,7 +80,7 @@ pub fn get_all_files<'a, I: Iterator<Item = &'a str>>(paths: I,
|
|||
}
|
||||
} else {
|
||||
let walker = WalkDir::new(path).into_iter().filter_entry(|entry| {
|
||||
for ig in ignored_directories.to_owned() {
|
||||
for ig in ignored_directories.clone() {
|
||||
if entry.path().to_str().unwrap().contains(&*ig) {
|
||||
return false;
|
||||
}
|
||||
|
@ -143,23 +149,7 @@ pub fn get_filetype_from_shebang<P: AsRef<Path>>(file: P) -> Option<&'static str
|
|||
}
|
||||
}
|
||||
|
||||
/// This originally too a &[u8], but the u8 didn't directly correspond with the hexadecimal u8, so
|
||||
/// it had to be changed to a String, and add the rustc_serialize dependency.
|
||||
pub fn convert_input(contents: String) -> Option<BTreeMap<String, Language>> {
|
||||
if contents.is_empty() {
|
||||
None
|
||||
} else if let Ok(result) = serde_json::from_str(&*contents) {
|
||||
Some(result)
|
||||
} else if let Ok(result) = serde_yaml::from_str(&*contents) {
|
||||
Some(result)
|
||||
} else if let Ok(result) = serde_cbor::from_slice(&*contents.from_hex().unwrap()) {
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code, unused_imports)]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod consts;
|
||||
mod fs;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
pub mod consts;
|
||||
pub mod fs;
|
||||
|
||||
pub use consts::*;
|
||||
pub use fs::*;
|
||||
pub use self::consts::*;
|
||||
pub use self::fs::*;
|
||||
|
|
Loading…
Reference in a new issue