From eb12da0308e0c5566b294c3d0cd1917e58af4e5b Mon Sep 17 00:00:00 2001 From: ChristianVisintin Date: Sun, 20 Dec 2020 15:36:48 +0100 Subject: [PATCH] Utils into multiple files --- src/filetransfer/ftp_transfer.rs | 4 +- src/filetransfer/scp_transfer.rs | 4 +- src/fs/mod.rs | 28 +-- src/main.rs | 2 +- src/system/bookmarks_client.rs | 4 +- src/ui/activities/auth_activity/layout.rs | 2 +- .../filetransfer_activity/layout.rs | 8 +- .../filetransfer_activity/session.rs | 3 +- src/utils/fmt.rs | 172 +++++++++++++++ src/utils/hash.rs | 75 +++++++ src/utils/mod.rs | 29 +++ src/{utils.rs => utils/parser.rs} | 208 +----------------- 12 files changed, 316 insertions(+), 223 deletions(-) create mode 100644 src/utils/fmt.rs create mode 100644 src/utils/hash.rs create mode 100644 src/utils/mod.rs rename src/{utils.rs => utils/parser.rs} (65%) diff --git a/src/filetransfer/ftp_transfer.rs b/src/filetransfer/ftp_transfer.rs index 4c3bddd..643adbe 100644 --- a/src/filetransfer/ftp_transfer.rs +++ b/src/filetransfer/ftp_transfer.rs @@ -30,7 +30,7 @@ extern crate regex; use super::{FileTransfer, FileTransferError, FileTransferErrorType}; use crate::fs::{FsDirectory, FsEntry, FsFile}; -use crate::utils::lstime_to_systime; +use crate::utils::parser::parse_lstime; // Includes use ftp4::native_tls::TlsConnector; @@ -142,7 +142,7 @@ impl FtpFileTransfer { (owner_pex, group_pex, others_pex) }; // Parse mtime and convert to SystemTime - let mtime: SystemTime = match lstime_to_systime( + let mtime: SystemTime = match parse_lstime( metadata.get(7).unwrap().as_str(), "%b %d %Y", "%b %d %H:%M", diff --git a/src/filetransfer/scp_transfer.rs b/src/filetransfer/scp_transfer.rs index 08fbe2a..2843f39 100644 --- a/src/filetransfer/scp_transfer.rs +++ b/src/filetransfer/scp_transfer.rs @@ -30,7 +30,7 @@ extern crate ssh2; // Locals use super::{FileTransfer, FileTransferError, FileTransferErrorType}; use crate::fs::{FsDirectory, FsEntry, FsFile}; -use crate::utils::lstime_to_systime; +use crate::utils::parser::parse_lstime; // Includes use regex::Regex; @@ -151,7 +151,7 @@ impl ScpFileTransfer { (owner_pex, group_pex, others_pex) }; // Parse mtime and convert to SystemTime - let mtime: SystemTime = match lstime_to_systime( + let mtime: SystemTime = match parse_lstime( metadata.get(7).unwrap().as_str(), "%b %d %Y", "%b %d %H:%M", diff --git a/src/fs/mod.rs b/src/fs/mod.rs index cd70851..4ce73f9 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -27,7 +27,7 @@ extern crate bytesize; #[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))] extern crate users; -use crate::utils::{fmt_pex, time_to_str}; +use crate::utils::fmt::{fmt_pex, fmt_time}; use bytesize::ByteSize; use std::path::PathBuf; @@ -271,7 +271,7 @@ impl std::fmt::Display for FsEntry { // Get byte size let size: ByteSize = ByteSize(self.get_size() as u64); // Get date - let datetime: String = time_to_str(self.get_last_change_time(), "%b %d %Y %H:%M"); + let datetime: String = fmt_time(self.get_last_change_time(), "%b %d %Y %H:%M"); // Set file name (or elide if too long) let name: String = self.get_name(); let name: String = match name.len() >= 24 { @@ -467,7 +467,7 @@ mod tests { format!("{}", entry), format!( "bar.txt \t-rw-r--r-- \troot \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); #[cfg(target_os = "windows")] @@ -475,7 +475,7 @@ mod tests { format!("{}", entry), format!( "bar.txt \t-rw-r--r-- \t0 \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); // Elide name @@ -498,7 +498,7 @@ mod tests { format!("{}", entry), format!( "piroparoporoperoperu... \t-rw-r--r-- \troot \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); #[cfg(target_os = "windows")] @@ -506,7 +506,7 @@ mod tests { format!("{}", entry), format!( "piroparoporoperoperu... \t-rw-r--r-- \t0 \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); // No pex @@ -529,7 +529,7 @@ mod tests { format!("{}", entry), format!( "bar.txt \t-????????? \troot \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); #[cfg(target_os = "windows")] @@ -537,7 +537,7 @@ mod tests { format!("{}", entry), format!( "bar.txt \t-????????? \t0 \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); // No user @@ -560,7 +560,7 @@ mod tests { format!("{}", entry), format!( "bar.txt \t-????????? \t0 \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); #[cfg(target_os = "windows")] @@ -568,7 +568,7 @@ mod tests { format!("{}", entry), format!( "bar.txt \t-????????? \t0 \t8.2 KB \t{}", - time_to_str(t, "%b %d %Y %H:%M") + fmt_time(t, "%b %d %Y %H:%M") ) ); } @@ -593,7 +593,7 @@ mod tests { format!("{}", entry), format!( "projects \tdrwxr-xr-x \troot \t4.1 KB \t{}", - time_to_str(t_now, "%b %d %Y %H:%M") + fmt_time(t_now, "%b %d %Y %H:%M") ) ); #[cfg(target_os = "windows")] @@ -601,7 +601,7 @@ mod tests { format!("{}", entry), format!( "projects \tdrwxr-xr-x \t0 \t4.1 KB \t{}", - time_to_str(t_now, "%b %d %Y %H:%M") + fmt_time(t_now, "%b %d %Y %H:%M") ) ); // No pex, no user @@ -622,7 +622,7 @@ mod tests { format!("{}", entry), format!( "projects \td????????? \t0 \t4.1 KB \t{}", - time_to_str(t_now, "%b %d %Y %H:%M") + fmt_time(t_now, "%b %d %Y %H:%M") ) ); #[cfg(target_os = "windows")] @@ -630,7 +630,7 @@ mod tests { format!("{}", entry), format!( "projects \td????????? \t0 \t4.1 KB \t{}", - time_to_str(t_now, "%b %d %Y %H:%M") + fmt_time(t_now, "%b %d %Y %H:%M") ) ); } diff --git a/src/main.rs b/src/main.rs index c407928..4682f1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -119,7 +119,7 @@ fn main() { let extra_args: Vec = matches.free; if let Some(remote) = extra_args.get(0) { // Parse address - match utils::parse_remote_opt(remote) { + match utils::parser::parse_remote_opt(remote) { Ok((addr, portn, proto, user)) => { // Set params address = Some(addr); diff --git a/src/system/bookmarks_client.rs b/src/system/bookmarks_client.rs index e8c4bba..00803f0 100644 --- a/src/system/bookmarks_client.rs +++ b/src/system/bookmarks_client.rs @@ -31,7 +31,7 @@ extern crate rand; use crate::bookmarks::serializer::BookmarkSerializer; use crate::bookmarks::{Bookmark, SerializerError, SerializerErrorKind, UserHosts}; use crate::filetransfer::FileTransferProtocol; -use crate::utils::time_to_str; +use crate::utils::fmt::fmt_time; // Ext use magic_crypt::MagicCryptTrait; use rand::{distributions::Alphanumeric, Rng}; @@ -220,7 +220,7 @@ impl BookmarksClient { } } } - let name: String = time_to_str(SystemTime::now(), "ISO%Y%m%dT%H%M%S"); + let name: String = fmt_time(SystemTime::now(), "ISO%Y%m%dT%H%M%S"); self.hosts.recents.insert(name, host); } diff --git a/src/ui/activities/auth_activity/layout.rs b/src/ui/activities/auth_activity/layout.rs index f48bcab..069b613 100644 --- a/src/ui/activities/auth_activity/layout.rs +++ b/src/ui/activities/auth_activity/layout.rs @@ -27,7 +27,7 @@ use super::{ AuthActivity, Context, DialogYesNoOption, FileTransferProtocol, InputField, InputForm, InputMode, PopupType, }; -use crate::utils::align_text_center; +use crate::utils::fmt::align_text_center; use tui::{ layout::{Constraint, Corner, Direction, Layout, Rect}, diff --git a/src/ui/activities/filetransfer_activity/layout.rs b/src/ui/activities/filetransfer_activity/layout.rs index ebb4bf4..fe16831 100644 --- a/src/ui/activities/filetransfer_activity/layout.rs +++ b/src/ui/activities/filetransfer_activity/layout.rs @@ -28,7 +28,7 @@ use super::{ Context, DialogYesNoOption, FileExplorerTab, FileTransferActivity, FsEntry, InputField, InputMode, LogLevel, LogRecord, PopupType, }; -use crate::utils::{align_text_center, time_to_str}; +use crate::utils::fmt::{align_text_center, fmt_time}; use bytesize::ByteSize; use std::path::{Path, PathBuf}; @@ -484,10 +484,10 @@ impl FileTransferActivity { // Get name and path let abs_path: PathBuf = fsentry.get_abs_path(); let name: String = fsentry.get_name(); - let ctime: String = time_to_str(fsentry.get_creation_time(), "%b %d %Y %H:%M:%S"); + let ctime: String = fmt_time(fsentry.get_creation_time(), "%b %d %Y %H:%M:%S"); let atime: String = - time_to_str(fsentry.get_last_access_time(), "%b %d %Y %H:%M:%S"); - let mtime: String = time_to_str(fsentry.get_creation_time(), "%b %d %Y %H:%M:%S"); + fmt_time(fsentry.get_last_access_time(), "%b %d %Y %H:%M:%S"); + let mtime: String = fmt_time(fsentry.get_creation_time(), "%b %d %Y %H:%M:%S"); let (bsize, size): (ByteSize, usize) = (ByteSize(fsentry.get_size() as u64), fsentry.get_size()); let user: Option = fsentry.get_user(); diff --git a/src/ui/activities/filetransfer_activity/session.rs b/src/ui/activities/filetransfer_activity/session.rs index 8c6506a..f1e0f23 100644 --- a/src/ui/activities/filetransfer_activity/session.rs +++ b/src/ui/activities/filetransfer_activity/session.rs @@ -28,7 +28,8 @@ extern crate tempfile; // Locals use super::{FileTransferActivity, InputMode, LogLevel, PopupType}; use crate::fs::{FsEntry, FsFile}; -use crate::utils::{fmt_millis, hash_sha256_file}; +use crate::utils::fmt::fmt_millis; +use crate::utils::hash::hash_sha256_file; // Ext use bytesize::ByteSize; diff --git a/src/utils/fmt.rs b/src/utils/fmt.rs new file mode 100644 index 0000000..7af3f49 --- /dev/null +++ b/src/utils/fmt.rs @@ -0,0 +1,172 @@ +//! ## Fmt +//! +//! `fmt` is the module which provides utilities for formatting + +/* +* +* Copyright (C) 2020 Christian Visintin - christian.visintin1997@gmail.com +* +* This file is part of "TermSCP" +* +* TermSCP is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* TermSCP is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with TermSCP. If not, see . +* +*/ + +extern crate chrono; +extern crate textwrap; + +use chrono::prelude::*; +use std::time::{Duration, SystemTime}; + +/// ### fmt_pex +/// +/// Convert 3 bytes of permissions value into ls notation (e.g. rwx-wx--x) +pub fn fmt_pex(owner: u8, group: u8, others: u8) -> String { + let mut mode: String = String::with_capacity(9); + let read: u8 = (owner >> 2) & 0x1; + let write: u8 = (owner >> 1) & 0x1; + let exec: u8 = owner & 0x1; + mode.push_str(match read { + 1 => "r", + _ => "-", + }); + mode.push_str(match write { + 1 => "w", + _ => "-", + }); + mode.push_str(match exec { + 1 => "x", + _ => "-", + }); + let read: u8 = (group >> 2) & 0x1; + let write: u8 = (group >> 1) & 0x1; + let exec: u8 = group & 0x1; + mode.push_str(match read { + 1 => "r", + _ => "-", + }); + mode.push_str(match write { + 1 => "w", + _ => "-", + }); + mode.push_str(match exec { + 1 => "x", + _ => "-", + }); + let read: u8 = (others >> 2) & 0x1; + let write: u8 = (others >> 1) & 0x1; + let exec: u8 = others & 0x1; + mode.push_str(match read { + 1 => "r", + _ => "-", + }); + mode.push_str(match write { + 1 => "w", + _ => "-", + }); + mode.push_str(match exec { + 1 => "x", + _ => "-", + }); + mode +} + +/// ### instant_to_str +/// +/// Format a `Instant` into a time string +pub fn fmt_time(time: SystemTime, fmt: &str) -> String { + let datetime: DateTime = time.into(); + format!("{}", datetime.format(fmt)) +} + +/// ### fmt_millis +/// +/// Format duration as {secs}.{millis} +pub fn fmt_millis(duration: Duration) -> String { + let seconds: u128 = duration.as_millis() / 1000; + let millis: u128 = duration.as_millis() % 1000; + format!("{}.{:0width$}", seconds, millis, width = 3) +} + +/// align_text_center +/// +/// Align text to center for a given width +pub fn align_text_center(text: &str, width: u16) -> String { + let indent_size: usize = match (width as usize) >= text.len() { + // NOTE: The check prevents underflow + true => (width as usize - text.len()) / 2, + false => 0, + }; + textwrap::indent( + text, + (0..indent_size).map(|_| " ").collect::().as_str(), + ) + .trim_end() + .to_string() +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_utils_fmt_pex() { + assert_eq!(fmt_pex(7, 7, 7), String::from("rwxrwxrwx")); + assert_eq!(fmt_pex(7, 5, 5), String::from("rwxr-xr-x")); + assert_eq!(fmt_pex(6, 6, 6), String::from("rw-rw-rw-")); + assert_eq!(fmt_pex(6, 4, 4), String::from("rw-r--r--")); + assert_eq!(fmt_pex(6, 0, 0), String::from("rw-------")); + assert_eq!(fmt_pex(0, 0, 0), String::from("---------")); + assert_eq!(fmt_pex(4, 4, 4), String::from("r--r--r--")); + assert_eq!(fmt_pex(1, 2, 1), String::from("--x-w---x")); + } + + #[test] + fn test_utils_fmt_time() { + let system_time: SystemTime = SystemTime::from(SystemTime::UNIX_EPOCH); + assert_eq!( + fmt_time(system_time, "%Y-%m-%d"), + String::from("1970-01-01") + ); + } + + #[test] + fn test_utils_align_text_center() { + assert_eq!( + align_text_center("hello world!", 24), + String::from(" hello world!") + ); + // Bad case + assert_eq!( + align_text_center("hello world!", 8), + String::from("hello world!") + ); + } + #[test] + fn test_utils_fmt_millis() { + assert_eq!( + fmt_millis(Duration::from_millis(2048)), + String::from("2.048") + ); + assert_eq!( + fmt_millis(Duration::from_millis(8192)), + String::from("8.192") + ); + assert_eq!( + fmt_millis(Duration::from_millis(18192)), + String::from("18.192") + ); + } +} diff --git a/src/utils/hash.rs b/src/utils/hash.rs new file mode 100644 index 0000000..ea87645 --- /dev/null +++ b/src/utils/hash.rs @@ -0,0 +1,75 @@ +//! ## Hash +//! +//! `hash` is the module which provides utilities for calculating digests + +/* +* +* Copyright (C) 2020 Christian Visintin - christian.visintin1997@gmail.com +* +* This file is part of "TermSCP" +* +* TermSCP is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* TermSCP is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with TermSCP. If not, see . +* +*/ + +extern crate data_encoding; +extern crate ring; + +use data_encoding::HEXLOWER; +use ring::digest::{Context, Digest, SHA256}; +use std::fs::File; +use std::io::Read; +use std::path::Path; + +/// ### hash_sha256_file +/// +/// Get SHA256 of provided path +pub fn hash_sha256_file(file: &Path) -> Result { + // Open file + let mut reader: File = File::open(file)?; + let mut context = Context::new(&SHA256); + let mut buffer = [0; 8192]; + loop { + let count = reader.read(&mut buffer)?; + if count == 0 { + break; + } + context.update(&buffer[..count]); + } + // Finish context + let digest: Digest = context.finish(); + Ok(HEXLOWER.encode(digest.as_ref())) +} + +#[cfg(test)] +mod tests { + + use super::*; + + use std::io::Write; + + #[test] + fn test_utils_hash_sha256() { + let tmp: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap(); + // Write + let mut fhnd: File = File::create(tmp.path()).unwrap(); + assert!(fhnd.write_all(b"Hello world!\n").is_ok()); + assert_eq!( + *hash_sha256_file(tmp.path()).ok().as_ref().unwrap(), + String::from("0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8") + ); + // Bad file + assert!(hash_sha256_file(Path::new("/tmp/oiojjt5ig/aiehgoiwg")).is_err()); + } +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..7c02112 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1,29 @@ +//! ## Utils +//! +//! `utils` is the module which provides utilities of different kind + +/* +* +* Copyright (C) 2020 Christian Visintin - christian.visintin1997@gmail.com +* +* This file is part of "TermSCP" +* +* TermSCP is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* TermSCP is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with TermSCP. If not, see . +* +*/ + +// modules +pub mod fmt; +pub mod hash; +pub mod parser; diff --git a/src/utils.rs b/src/utils/parser.rs similarity index 65% rename from src/utils.rs rename to src/utils/parser.rs index 6160266..1410e5c 100644 --- a/src/utils.rs +++ b/src/utils/parser.rs @@ -1,6 +1,6 @@ -//! ## Utils +//! ## Parser //! -//! `utils` is the module which provides utilities of different kind +//! `parser` is the module which provides utilities for parsing different kind of stuff /* * @@ -25,20 +25,12 @@ // Dependencies extern crate chrono; -extern crate data_encoding; -extern crate ring; -extern crate textwrap; extern crate whoami; use crate::filetransfer::FileTransferProtocol; use chrono::format::ParseError; use chrono::prelude::*; -use data_encoding::HEXLOWER; -use ring::digest::{Context, Digest, SHA256}; -use std::fs::File; -use std::io::Read; -use std::path::Path; use std::time::{Duration, SystemTime}; /// ### parse_remote_opt @@ -152,87 +144,13 @@ pub fn parse_remote_opt( Ok((address, port, protocol, username)) } -/// ### fmt_pex -/// -/// Convert 3 bytes of permissions value into ls notation (e.g. rwx-wx--x) -pub fn fmt_pex(owner: u8, group: u8, others: u8) -> String { - let mut mode: String = String::with_capacity(9); - let read: u8 = (owner >> 2) & 0x1; - let write: u8 = (owner >> 1) & 0x1; - let exec: u8 = owner & 0x1; - mode.push_str(match read { - 1 => "r", - _ => "-", - }); - mode.push_str(match write { - 1 => "w", - _ => "-", - }); - mode.push_str(match exec { - 1 => "x", - _ => "-", - }); - let read: u8 = (group >> 2) & 0x1; - let write: u8 = (group >> 1) & 0x1; - let exec: u8 = group & 0x1; - mode.push_str(match read { - 1 => "r", - _ => "-", - }); - mode.push_str(match write { - 1 => "w", - _ => "-", - }); - mode.push_str(match exec { - 1 => "x", - _ => "-", - }); - let read: u8 = (others >> 2) & 0x1; - let write: u8 = (others >> 1) & 0x1; - let exec: u8 = others & 0x1; - mode.push_str(match read { - 1 => "r", - _ => "-", - }); - mode.push_str(match write { - 1 => "w", - _ => "-", - }); - mode.push_str(match exec { - 1 => "x", - _ => "-", - }); - mode -} - -/// ### instant_to_str -/// -/// Format a `Instant` into a time string -pub fn time_to_str(time: SystemTime, fmt: &str) -> String { - let datetime: DateTime = time.into(); - format!("{}", datetime.format(fmt)) -} - -/// ### fmt_millis -/// -/// Format duration as {secs}.{millis} -pub fn fmt_millis(duration: Duration) -> String { - let seconds: u128 = duration.as_millis() / 1000; - let millis: u128 = duration.as_millis() % 1000; - format!("{}.{:0width$}", seconds, millis, width = 3) -} - -/// ### lstime_to_systime +/// ### parse_lstime /// /// Convert ls syntax time to System Time /// ls time has two possible syntax: /// 1. if year is current: %b %d %H:%M (e.g. Nov 5 13:46) /// 2. else: %b %d %Y (e.g. Nov 5 2019) -pub fn lstime_to_systime( - tm: &str, - fmt_year: &str, - fmt_hours: &str, -) -> Result { +pub fn parse_lstime(tm: &str, fmt_year: &str, fmt_hours: &str) -> Result { let datetime: NaiveDateTime = match NaiveDate::parse_from_str(tm, fmt_year) { Ok(date) => { // Case 2. @@ -261,50 +179,11 @@ pub fn lstime_to_systime( .unwrap_or(SystemTime::UNIX_EPOCH)) } -/// align_text_center -/// -/// Align text to center for a given width -pub fn align_text_center(text: &str, width: u16) -> String { - let indent_size: usize = match (width as usize) >= text.len() { - // NOTE: The check prevents underflow - true => (width as usize - text.len()) / 2, - false => 0, - }; - textwrap::indent( - text, - (0..indent_size).map(|_| " ").collect::().as_str(), - ) - .trim_end() - .to_string() -} - -/// ### hash_sha256_file -/// -/// Get SHA256 of provided path -pub fn hash_sha256_file(file: &Path) -> Result { - // Open file - let mut reader: File = File::open(file)?; - let mut context = Context::new(&SHA256); - let mut buffer = [0; 8192]; - loop { - let count = reader.read(&mut buffer)?; - if count == 0 { - break; - } - context.update(&buffer[..count]); - } - // Finish context - let digest: Digest = context.finish(); - Ok(HEXLOWER.encode(digest.as_ref())) -} - #[cfg(test)] mod tests { use super::*; - use std::io::Write; - #[test] fn test_utils_parse_remote_opt() { // Base case @@ -395,31 +274,10 @@ mod tests { } #[test] - fn test_utils_fmt_pex() { - assert_eq!(fmt_pex(7, 7, 7), String::from("rwxrwxrwx")); - assert_eq!(fmt_pex(7, 5, 5), String::from("rwxr-xr-x")); - assert_eq!(fmt_pex(6, 6, 6), String::from("rw-rw-rw-")); - assert_eq!(fmt_pex(6, 4, 4), String::from("rw-r--r--")); - assert_eq!(fmt_pex(6, 0, 0), String::from("rw-------")); - assert_eq!(fmt_pex(0, 0, 0), String::from("---------")); - assert_eq!(fmt_pex(4, 4, 4), String::from("r--r--r--")); - assert_eq!(fmt_pex(1, 2, 1), String::from("--x-w---x")); - } - - #[test] - fn test_utils_time_to_str() { - let system_time: SystemTime = SystemTime::from(SystemTime::UNIX_EPOCH); - assert_eq!( - time_to_str(system_time, "%Y-%m-%d"), - String::from("1970-01-01") - ); - } - - #[test] - fn test_utils_lstime_to_systime() { + fn test_utils_parse_lstime() { // Good cases assert_eq!( - lstime_to_systime("Nov 5 16:32", "%b %d %Y", "%b %d %H:%M") + parse_lstime("Nov 5 16:32", "%b %d %Y", "%b %d %H:%M") .ok() .unwrap() .duration_since(SystemTime::UNIX_EPOCH) @@ -428,7 +286,7 @@ mod tests { Duration::from_secs(1604593920) ); assert_eq!( - lstime_to_systime("Dec 2 21:32", "%b %d %Y", "%b %d %H:%M") + parse_lstime("Dec 2 21:32", "%b %d %Y", "%b %d %H:%M") .ok() .unwrap() .duration_since(SystemTime::UNIX_EPOCH) @@ -437,7 +295,7 @@ mod tests { Duration::from_secs(1606944720) ); assert_eq!( - lstime_to_systime("Nov 5 2018", "%b %d %Y", "%b %d %H:%M") + parse_lstime("Nov 5 2018", "%b %d %Y", "%b %d %H:%M") .ok() .unwrap() .duration_since(SystemTime::UNIX_EPOCH) @@ -446,7 +304,7 @@ mod tests { Duration::from_secs(1541376000) ); assert_eq!( - lstime_to_systime("Mar 18 2018", "%b %d %Y", "%b %d %H:%M") + parse_lstime("Mar 18 2018", "%b %d %Y", "%b %d %H:%M") .ok() .unwrap() .duration_since(SystemTime::UNIX_EPOCH) @@ -455,50 +313,8 @@ mod tests { Duration::from_secs(1521331200) ); // bad cases - assert!(lstime_to_systime("Oma 31 2018", "%b %d %Y", "%b %d %H:%M").is_err()); - assert!(lstime_to_systime("Feb 31 2018", "%b %d %Y", "%b %d %H:%M").is_err()); - assert!(lstime_to_systime("Feb 15 25:32", "%b %d %Y", "%b %d %H:%M").is_err()); - } - - #[test] - fn test_utils_align_text_center() { - assert_eq!( - align_text_center("hello world!", 24), - String::from(" hello world!") - ); - // Bad case - assert_eq!( - align_text_center("hello world!", 8), - String::from("hello world!") - ); - } - #[test] - fn test_utils_fmt_millis() { - assert_eq!( - fmt_millis(Duration::from_millis(2048)), - String::from("2.048") - ); - assert_eq!( - fmt_millis(Duration::from_millis(8192)), - String::from("8.192") - ); - assert_eq!( - fmt_millis(Duration::from_millis(18192)), - String::from("18.192") - ); - } - - #[test] - fn test_utils_hash_sha256() { - let tmp: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap(); - // Write - let mut fhnd: File = File::create(tmp.path()).unwrap(); - assert!(fhnd.write_all(b"Hello world!\n").is_ok()); - assert_eq!( - *hash_sha256_file(tmp.path()).ok().as_ref().unwrap(), - String::from("0ba904eae8773b70c75333db4de2f3ac45a8ad4ddba1b242f0b3cfc199391dd8") - ); - // Bad file - assert!(hash_sha256_file(Path::new("/tmp/oiojjt5ig/aiehgoiwg")).is_err()); + assert!(parse_lstime("Oma 31 2018", "%b %d %Y", "%b %d %H:%M").is_err()); + assert!(parse_lstime("Feb 31 2018", "%b %d %Y", "%b %d %H:%M").is_err()); + assert!(parse_lstime("Feb 15 25:32", "%b %d %Y", "%b %d %H:%M").is_err()); } }