1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use clap::Parser;
use rustutils_runnable::Runnable;
use std::error::Error;
use std::ffi::{OsStr, OsString};
use std::io::Write;
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};
#[derive(Parser, Clone, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct Basename {
path: PathBuf,
suffix: Option<OsString>,
}
pub fn remove_suffix<'a, 'b>(string: &'a OsStr, suffix: Option<&'b OsStr>) -> &'a OsStr {
if let Some(suffix) = suffix {
if suffix.len() <= string.len() {
if &string.as_bytes()[string.len() - suffix.len()..] == suffix.as_bytes() {
return OsStr::from_bytes(&string.as_bytes()[0..string.len() - suffix.len()]);
}
}
}
string
}
pub fn basename<'a, 'b>(path: &'a Path, suffix: Option<&'b OsStr>) -> &'a OsStr {
match path.file_name() {
Some(string) => remove_suffix(string, suffix),
None if path.as_os_str() == "" => OsStr::new(""),
None if path.ends_with("..") => OsStr::new(".."),
None => OsStr::new(""),
}
}
impl Runnable for Basename {
fn run(&self) -> Result<(), Box<dyn Error>> {
let mut stdout = std::io::stdout();
let path = basename(&self.path, self.suffix.as_deref());
stdout.write_all(&path.as_bytes())?;
stdout.write_all(&[b'\n'])?;
Ok(())
}
}