8 use crate::{dialogs::Confirmation, info, oof};
10 pub fn create_dir_if_non_existent(path: &Path) -> crate::Result<()> {
12 fs::create_dir_all(path)?;
13 info!("directory {} created.", to_utf(path));
18 /// Changes the process' current directory to the directory that contains the
19 /// file pointed to by `filename` and returns the directory that the process
20 /// was in before this function was called.
21 pub fn cd_into_same_dir_as(filename: &Path) -> crate::Result<PathBuf> {
22 let previous_location = env::current_dir()?;
24 let parent = filename.parent().ok_or(crate::Error::CompressingRootFolder)?;
26 env::set_current_dir(parent)?;
31 pub fn user_wants_to_overwrite(path: &Path, flags: &oof::Flags) -> crate::Result<bool> {
32 match (flags.is_present("yes"), flags.is_present("no")) {
34 unreachable!("This should've been cutted out in the ~/src/cli.rs filter flags function.")
36 (true, _) => return Ok(true),
37 (_, true) => return Ok(false),
41 let file_path_str = to_utf(path);
43 const OVERWRITE_CONFIRMATION_QUESTION: Confirmation =
44 Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE"));
46 OVERWRITE_CONFIRMATION_QUESTION.ask(Some(&file_path_str))
49 pub fn to_utf(os_str: impl AsRef<OsStr>) -> String {
50 let text = format!("{:?}", os_str.as_ref());
51 text.trim_matches('"').to_string()
58 /// Module with a list of bright colors.
60 #[cfg(target_family = "unix")]
62 pub const fn reset() -> &'static str {
65 pub const fn black() -> &'static str {
68 pub const fn blue() -> &'static str {
71 pub const fn cyan() -> &'static str {
74 pub const fn green() -> &'static str {
77 pub const fn magenta() -> &'static str {
80 pub const fn red() -> &'static str {
83 pub const fn white() -> &'static str {
86 pub const fn yellow() -> &'static str {
90 // Windows does not support ANSI escape codes
91 #[allow(dead_code, non_upper_case_globals)]
92 #[cfg(not(target_family = "unix"))]
94 pub fn empty() -> &'static str {
97 pub const reset: fn() -> &'static str = empty;
98 pub const black: fn() -> &'static str = empty;
99 pub const blue: fn() -> &'static str = empty;
100 pub const cyan: fn() -> &'static str = empty;
101 pub const green: fn() -> &'static str = empty;
102 pub const magenta: fn() -> &'static str = empty;
103 pub const red: fn() -> &'static str = empty;
104 pub const white: fn() -> &'static str = empty;
105 pub const yellow: fn() -> &'static str = empty;
109 const UNIT_PREFIXES: [&'static str; 6] = ["", "k", "M", "G", "T", "P"];
111 pub fn new(bytes: u64) -> Self {
112 Self { bytes: bytes as f64 }
116 impl std::fmt::Display for Bytes {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 let num = self.bytes;
119 debug_assert!(num >= 0.0);
121 return write!(f, "{} B", num);
123 let delimiter = 1000_f64;
124 let exponent = cmp::min((num.ln() / 6.90775).floor() as i32, 4);
126 write!(f, "{:.2} ", num / delimiter.powi(exponent))?;
127 write!(f, "{}B", Bytes::UNIT_PREFIXES[exponent as usize])
136 fn test_pretty_bytes_formatting() {
137 fn format_bytes(bytes: u64) -> String {
138 format!("{}", Bytes::new(bytes))
145 assert_eq!("0 B", format_bytes(0)); // This is weird
146 assert_eq!("1.00 B", format_bytes(b));
147 assert_eq!("999.00 B", format_bytes(b * 999));
148 assert_eq!("12.00 MB", format_bytes(mb * 12));
149 assert_eq!("123.00 MB", format_bytes(mb * 123));
150 assert_eq!("5.50 MB", format_bytes(mb * 5 + kb * 500));
151 assert_eq!("7.54 GB", format_bytes(gb * 7 + 540 * mb));
152 assert_eq!("1.20 TB", format_bytes(gb * 1200));
155 assert_eq!("234.00 B", format_bytes(234));
156 assert_eq!("999.00 B", format_bytes(999));
158 assert_eq!("2.23 kB", format_bytes(2234));
159 assert_eq!("62.50 kB", format_bytes(62500));
160 assert_eq!("329.99 kB", format_bytes(329990));
162 assert_eq!("2.75 MB", format_bytes(2750000));
163 assert_eq!("55.00 MB", format_bytes(55000000));
164 assert_eq!("987.65 MB", format_bytes(987654321));
166 assert_eq!("5.28 GB", format_bytes(5280000000));
167 assert_eq!("95.20 GB", format_bytes(95200000000));
168 assert_eq!("302.00 GB", format_bytes(302000000000));