ietf

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 82246d5972ddc33a9ec57486d1ea623763a5a301
parent 365a8e6eff692085c5e0d813954f43884624fb16
Author: cy6erlion <dev@merely.tech>
Date:   Tue, 12 Jan 2021 11:51:29 +0200

Merge branch 'storage-struct'

Diffstat:
Msrc/fetch.rs | 10++++------
Dsrc/lib.rs | 78------------------------------------------------------------------------------
Msrc/main.rs | 68+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/storage.rs | 241+++++++++++++++++++++++++++++++++++++++----------------------------------------
4 files changed, 181 insertions(+), 216 deletions(-)

diff --git a/src/fetch.rs b/src/fetch.rs @@ -1,21 +1,19 @@ // Download RFC index file -pub fn index() -> Result<(), minreq::Error> { +pub fn index() -> Result<Vec<String>, minreq::Error> { println!("Fetching RFC index"); let response = minreq::get("https://www.rfc-editor.org/rfc-index.txt").send()?; let data = scrape(response.as_str()?); - super::storage::persist_index(data); - Ok(()) + Ok(data) } // Download RFC localy -pub fn rfc(sn: u32) -> Result<(), minreq::Error> { +pub fn rfc(sn: u32) -> Result<String, minreq::Error> { println!("Fetching RFC #{}", sn); let address = format!("https://www.rfc-editor.org/rfc/rfc{}.txt", sn); println!("{}", address); let response = minreq::get(&address).send()?; - super::storage::persist_rfc(sn, response.as_str()?); - Ok(()) + Ok(String::from(response.as_str()?)) } // TODO: fix bug causing not to return the last RFC diff --git a/src/lib.rs b/src/lib.rs @@ -1,78 +0,0 @@ -extern crate dirs_next; -extern crate pager; - -use pager::Pager; -use std::fs::File; -use std::io::{BufReader, Read}; -use std::path::Path; - -mod fetch; -pub mod storage; - -pub fn list_view() { - if !storage::index_exists().unwrap() { - // Download all RFCs - fetch::index().unwrap(); - } - - let home_path = if let Some(p) = storage::get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; - - let path = format!("{}INDEX", home_path); - - let mut index = String::new(); - let f = File::open(&path).expect("Unable to open file"); - let mut br = BufReader::new(f); - let mut dots = ""; - - br.read_to_string(&mut index).expect("Unable to read INDEX"); - - Pager::with_pager("less -r").setup(); - - for line in index.lines() { - let line_words: Vec<&str> = line.split(' ').collect(); - let summerize: String = line.chars().skip(line_words[0].len()).take(77).collect(); - - if line.len() >= 77 { - dots = "..."; - } - - println!("{} | {}{}", line_words[0], summerize, dots); - - dots = ""; - } -} - -// Read RFC by serial number -pub fn read_rfc(rfc_number: u32) { - // check if RFC is downloaded - if !storage::is_rfc_downloaded(rfc_number).unwrap() { - // download RFC - fetch::rfc(rfc_number).unwrap(); - } - - let home_path = if let Some(p) = storage::get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; - - let path = format!("{}{}", home_path, rfc_number); - - let mut rfc = String::new(); - let f = File::open(&path).expect("Unable to open file"); - let mut br = BufReader::new(f); - br.read_to_string(&mut rfc).expect("Unable to read RFC"); - - // Read RFC - Pager::with_pager("less -r").setup(); - println!("{}", &rfc); -} - -// Update RFC -pub fn update() { - fetch::index().unwrap(); -} diff --git a/src/main.rs b/src/main.rs @@ -1,4 +1,12 @@ use clap::{App, Arg, SubCommand}; +extern crate pager; + +mod fetch; +pub mod storage; + +use pager::Pager; +use std::fs::File; +use std::io::{BufReader, Read}; fn main() { let matches = App::new("ietf") @@ -25,18 +33,38 @@ fn main() { .subcommand(SubCommand::with_name("clean").about("Remove the rfc directory")) .get_matches(); + let storage = storage::Storage::new(); + // Read RFC by serial number if let Some(n) = matches.value_of("Number") { - ietf::read_rfc( - n.parse::<u32>() - .expect("RFC Serial Number should be a numeric value!"), - ); + let rfc_number = n.parse::<u32>().unwrap(); + + // check if RFC is downloaded + if !storage.is_rfc_downloaded(rfc_number).unwrap() { + // download RFC + let rfc_data = fetch::rfc(rfc_number).unwrap(); + + // persist RFC + storage.persist_rfc(rfc_number, &rfc_data); + } + + let rfc_file_path = format!("{}{}", storage.rfc_dir_path, rfc_number); + + let mut rfc_data = String::new(); + let index_file = File::open(&rfc_file_path).expect("Unable to open file"); + let mut buffer_reader = BufReader::new(index_file); + buffer_reader + .read_to_string(&mut rfc_data) + .expect("Unable to read RFC"); + + Pager::with_pager("less -r").setup(); + println!("{}", &rfc_data); return; } // Removes RFC by serial number if let Some(n) = matches.value_of("Remove") { - ietf::storage::remove( + storage.remove( n.parse::<u32>() .expect("RFC Serial Number should be a numeric value!"), ); @@ -45,16 +73,38 @@ fn main() { // Update RFC index if let Some(_matches) = matches.subcommand_matches("update") { - ietf::update(); + storage.update_index(); return; } // Remove the ietf directory if let Some(_matches) = matches.subcommand_matches("clean") { - ietf::storage::clean(); + storage.clean(); return; } - // Display RFC list view - ietf::list_view(); + // ---------- Display RFC list view ------------ + let mut index_data = String::new(); + let index_file = File::open(&storage.index_file_path).expect("Unable to open file"); + let mut buffer_reader = BufReader::new(index_file); + let mut read_more_dots = ""; + + buffer_reader + .read_to_string(&mut index_data) + .expect("Unable to read INDEX"); + + Pager::with_pager("less -r").setup(); + + for line in index_data.lines() { + let line_words: Vec<&str> = line.split(' ').collect(); + let summerize: String = line.chars().skip(line_words[0].len()).take(77).collect(); + + if line.len() >= 77 { + read_more_dots = "..."; + } + + println!("{} | {}{}", line_words[0], summerize, read_more_dots); + + read_more_dots = ""; + } } diff --git a/src/storage.rs b/src/storage.rs @@ -3,147 +3,142 @@ use std::fs::OpenOptions; use std::io::prelude::*; use std::path::Path; -// Save index localy -pub fn persist_index(index: Vec<String>) { - let home_path = if let Some(p) = get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; - - let index_file_path = format!("{}INDEX", home_path); - - let _file = File::create(&index_file_path).expect("Unable to create file"); - let mut file = OpenOptions::new() - .write(true) - .append(true) - .open(&index_file_path) - .unwrap(); - - for rfc in index.iter() { - if let Err(e) = writeln!(file, "{}", rfc) { - eprintln!("Couldn't write to file: {}", e); +pub struct Storage { + pub rfc_dir_path: String, + pub index_file_path: String, +} + +impl Storage { + // Create new Storage instance + pub fn new() -> Self { + if let Some(home_path) = dirs_next::home_dir() { + let rfc_dir_path = if cfg!(unix) || cfg!(macos) { + format!("{}/rfc/", home_path.to_str().unwrap()) + } else if cfg!(windows) { + format!("{}\\rfc\\", home_path.to_str().unwrap()) + } else { + panic!("Unsupported OS"); + }; + + // Check if storage directory (~/rfc) has been created + // otherwise create storage directory + if !Path::new(&rfc_dir_path).exists() { + // create RFC storage directory + std::fs::create_dir(&rfc_dir_path).unwrap(); + } + + let index_file_path = format!("{}INDEX", &rfc_dir_path); + + // Check if RFC INDEX file is downloaded + if !Path::new(&index_file_path).exists() { + let _create_index = + File::create(&index_file_path).expect("Unable to creat INDEX file"); + + // Fetch remote INDEX file data + let data = super::fetch::index().unwrap(); + + // Persist RFC INDEX + Storage::persist_index(&index_file_path, data); + } + + Storage { + rfc_dir_path, + index_file_path, + } + } else { + panic!("Error: 'Could not find home directory!'"); } } -} -// Save RFC localy -pub fn persist_rfc(rfc_number: u32, rfc: &str) { - let home_path = if let Some(p) = get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; - - let rfc_file_path = format!("{}{}", home_path, rfc_number); - - let _file = File::create(&rfc_file_path).expect("Unable to create file"); - let mut file = OpenOptions::new() - .write(true) - .append(true) - .open(rfc_file_path) - .unwrap(); - - if let Err(e) = writeln!(file, "{}", rfc) { - eprintln!("Couldn't write to file: {}", e); + // Save index localy + pub fn persist_index(index_file_path: &str, data: Vec<String>) { + let mut file = OpenOptions::new() + .write(true) + .append(true) + .open(&index_file_path) + .unwrap(); + + for rfc in data.iter() { + if let Err(e) = writeln!(file, "{}", rfc) { + eprintln!("Couldn't write to file: {}", e); + } + } } -} -// Removes RFC by Serial Number -pub fn remove(rfc_number: u32) { - let home_path = if let Some(p) = get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; + // Update index + pub fn update_index(&self) { + if Path::new(&self.index_file_path).exists() { + std::fs::remove_file(&self.index_file_path).unwrap(); + } + + let _create_index = + File::create(&self.index_file_path).expect("Unable to creat INDEX file"); - let rfc_file_path = format!("{}{}", home_path, rfc_number); + // Fetch remote INDEX file data + let data = super::fetch::index().unwrap(); - if Path::new(&rfc_file_path).exists() { - std::fs::remove_file(&rfc_file_path).unwrap(); + // Persist RFC INDEX + Storage::persist_index(&self.index_file_path, data); } -} -// Removes the rfc directory -pub fn clean() -> () { - let rfc_directory_path = if let Some(p) = get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; + // Check if an RFC file has been downloaded locally + pub fn is_rfc_downloaded(&self, rfc_number: u32) -> Result<bool, ()> { + let rfc_file_path = format!("{}{}", self.rfc_dir_path, rfc_number); - if Path::new(&rfc_directory_path).exists() { - std::fs::remove_dir_all(&rfc_directory_path).unwrap(); + if Path::new(&rfc_file_path).exists() { + Ok(true) + } else { + Ok(false) + } } -} -// Check if an RFC file has been downloaded locally -pub fn is_rfc_downloaded(rfc_number: u32) -> Result<bool, ()> { - let home_path = if let Some(p) = get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; - - let rfc_file_path = format!("{}{}", &home_path, rfc_number); - - if Path::new(&rfc_file_path).exists() { - Ok(true) - } else { - initialize_storage().unwrap(); - Ok(false) + // Save RFC localy + pub fn persist_rfc(&self, rfc_number: u32, rfc_data: &str) { + let rfc_file_path = format!("{}{}", self.rfc_dir_path, rfc_number); + + let _file = File::create(&rfc_file_path).expect("Unable to create file"); + let mut file = OpenOptions::new() + .write(true) + .append(true) + .open(rfc_file_path) + .unwrap(); + + if let Err(e) = writeln!(file, "{}", rfc_data) { + eprintln!("Couldn't write to file: {}", e); + } } -} -// Check if storage directory (~/rfc) has been created -// if it does not, create the directory -fn initialize_storage() -> std::io::Result<()> { - let home_path = if let Some(p) = get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; - - if Path::new(&home_path).exists() { - Ok(()) - } else { - std::fs::create_dir(&home_path)?; - Ok(()) + // Removes RFC by Serial Number + pub fn remove(&self, rfc_number: u32) { + let rfc_file_path = format!("{}{}", &self.rfc_dir_path, rfc_number); + + if Path::new(&rfc_file_path).exists() { + std::fs::remove_file(&rfc_file_path).unwrap(); + } } -} -// Check if the rfc INDEX file has been downloaded -pub fn index_exists() -> Result<bool, ()> { - let home_path = if let Some(p) = get_home_path() { - p - } else { - panic!("Error: 'Could not find home directory!'"); - }; - - let index_file_path = format!("{}INDEX", home_path); - - if Path::new(&index_file_path).exists() { - Ok(true) - } else { - initialize_storage().unwrap(); - Ok(false) + // Removes the rfc directory + pub fn clean(&self) { + if Path::new(&self.rfc_dir_path).exists() { + std::fs::remove_dir_all(&self.rfc_dir_path).unwrap(); + } } -} -// Get path of home directory -// (`~/rfc/` on unix systems and `C:\Users\{NAME}` on windows) -pub fn get_home_path() -> Option<String> { - if let Some(home_path) = dirs_next::home_dir() { - let path = if cfg!(unix) || cfg!(macos) { - format!("{}/rfc/", home_path.to_str().unwrap()) - } else if cfg!(windows) { - format!("{}\\rfc\\", home_path.to_str().unwrap()) + // Get path of home directory + // (`~/rfc/` on unix systems and `C:\Users\{NAME}` on windows) + pub fn get_home_path() -> Option<String> { + if let Some(home_path) = dirs_next::home_dir() { + let path = if cfg!(unix) || cfg!(macos) { + format!("{}/rfc/", home_path.to_str().unwrap()) + } else if cfg!(windows) { + format!("{}\\rfc\\", home_path.to_str().unwrap()) + } else { + panic!("Unsupported OS"); + }; + + Some(path) } else { - panic!("Unsupported OS"); - }; - - Some(path) - } else { - None + None + } } }