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