From b6be708d5e437116b31dbf837316c04709e2c16d Mon Sep 17 00:00:00 2001 From: peshwar9 Date: Fri, 28 Aug 2020 00:03:50 +0530 Subject: [PATCH] added chapter 6 code --- chapter6/rstat/.DS_Store | Bin 0 -> 6148 bytes chapter6/rstat/.gitignore | 1 + chapter6/rstat/Cargo.lock | 223 +++++++++++++++++++++++++++++++++ chapter6/rstat/Cargo.toml | 10 ++ chapter6/rstat/src/errors.rs | 37 ++++++ chapter6/rstat/src/main.rs | 32 +++++ chapter6/rstat/src/srcstats.rs | 78 ++++++++++++ 7 files changed, 381 insertions(+) create mode 100644 chapter6/rstat/.DS_Store create mode 100644 chapter6/rstat/.gitignore create mode 100644 chapter6/rstat/Cargo.lock create mode 100644 chapter6/rstat/Cargo.toml create mode 100644 chapter6/rstat/src/errors.rs create mode 100644 chapter6/rstat/src/main.rs create mode 100644 chapter6/rstat/src/srcstats.rs diff --git a/chapter6/rstat/.DS_Store b/chapter6/rstat/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Result<(), fmt::Error> { + write!(f, "{}", self) + } +} + +impl From<&str> for StatsError { + fn from(s: &str) -> Self { + StatsError { + message: s.to_string(), + } + } +} + +impl From for StatsError { + fn from(e: io::Error) -> Self { + StatsError { + message: e.to_string(), + } + } +} + +impl From for StatsError { + fn from(_e: std::num::TryFromIntError) -> Self { + StatsError { + message: "Number conversion error".to_string(), + } + } +} diff --git a/chapter6/rstat/src/main.rs b/chapter6/rstat/src/main.rs new file mode 100644 index 0000000..d2bf7ed --- /dev/null +++ b/chapter6/rstat/src/main.rs @@ -0,0 +1,32 @@ +use std::path::PathBuf; +use structopt::StructOpt; +mod srcstats; +use srcstats::get_summary_src_stats; + +mod errors; +use errors::StatsError; + +#[derive(Debug, StructOpt)] +#[structopt( + name = "rstat", + about = "This is a tool to generate statistics on Rust projects" +)] +struct Opt { + #[structopt(name = "source directory", parse(from_os_str))] + in_dir: PathBuf, + #[structopt(name = "mode", short)] + mode: String, +} + +fn main() -> Result<(), StatsError> { + let opt = Opt::from_args(); + let mode = &opt.mode[..]; + match mode { + "src" => { + let stats = get_summary_src_stats(&opt.in_dir)?; + println!("Summary stats: {:?}", stats); + } + _ => println!("Sorry, no stats"), + } + Ok(()) +} diff --git a/chapter6/rstat/src/srcstats.rs b/chapter6/rstat/src/srcstats.rs new file mode 100644 index 0000000..0c5ac6d --- /dev/null +++ b/chapter6/rstat/src/srcstats.rs @@ -0,0 +1,78 @@ +use super::errors::StatsError; +use std::convert::TryFrom; +use std::ffi::OsStr; +use std::fs; +use std::fs::DirEntry; +use std::path::{Path, PathBuf}; + +// Struct to hold the stats +#[derive(Debug)] +pub struct SrcStats { + pub number_of_files: u32, + pub loc: u32, + pub comments: u32, + pub blanks: u32, +} + +pub fn get_src_stats_for_file(file_name: &Path) -> Result { + let file_contents = fs::read_to_string(file_name)?; + let mut loc = 0; + let mut blanks = 0; + let mut comments = 0; + + for line in file_contents.lines() { + if line.len() == 0 { + blanks += 1; + } else if line.starts_with("//") { + comments += 1; + } else { + loc += 1; + } + } + let source_stats = SrcStats { + number_of_files: u32::try_from(file_contents.lines().count())?, + loc: loc, + comments: comments, + blanks: blanks, + }; + Ok(source_stats) +} + +pub fn get_summary_src_stats(in_dir: &Path) -> Result { + let mut total_loc = 0; + let mut total_comments = 0; + let mut total_blanks = 0; + let mut dir_entries: Vec = vec![in_dir.to_path_buf()]; + let mut file_entries: Vec = vec![]; + + // Recursively iterate over directory entries to get flat list of .rs files + + while let Some(entry) = dir_entries.pop() { + for inner_entry in fs::read_dir(&entry)? { + if let Ok(entry) = inner_entry { + if entry.path().is_dir() { + dir_entries.push(entry.path()); + } else { + if entry.path().extension() == Some(OsStr::new("rs")) { + file_entries.push(entry); + } + } + } + } + } + let file_count = file_entries.len(); + // Compute the stats + for entry in file_entries { + let stat = get_src_stats_for_file(&entry.path())?; + total_loc += stat.loc; + total_blanks += stat.blanks; + total_comments += stat.comments; + } + + Ok(SrcStats { + number_of_files: u32::try_from(file_count)?, + loc: total_loc, + comments: total_comments, + blanks: total_blanks, + }) +}