use std::path::{Path, PathBuf};
use anyhow::Context;
#[cfg(target_os = "linux")]
pub const CLASSPATH_SEP: char = ':';
#[cfg(target_os = "macos")]
pub const CLASSPATH_SEP: char = ':';
#[cfg(target_os = "windows")]
pub const CLASSPATH_SEP: char = ';';
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Classpath {
string: String,
}
impl Classpath {
pub fn new() -> Self {
Self {
string: String::new(),
}
}
pub fn add_sep(&mut self) {
self.string.push(CLASSPATH_SEP);
}
pub fn add(&mut self, string: &str) {
if let Some(last_char) = self.string.chars().last() {
if last_char != CLASSPATH_SEP {
self.add_sep();
}
}
self.string.push_str(string);
}
pub fn add_path(&mut self, path: &Path) -> anyhow::Result<()> {
self.add(
path.to_str()
.context("Failed to convert path to a string")?,
);
Ok(())
}
pub fn add_multiple<I: AsRef<str>>(&mut self, strings: impl Iterator<Item = I>) {
for string in strings {
self.add(string.as_ref());
}
}
pub fn extend(&mut self, other: Classpath) {
self.add(&other.string)
}
pub fn get_str(&self) -> String {
self.string.clone()
}
pub fn get_entries(&self) -> Vec<&str> {
self.string.split(CLASSPATH_SEP).collect()
}
pub fn get_paths(&self) -> Vec<PathBuf> {
self.string
.split(CLASSPATH_SEP)
.map(PathBuf::from)
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_classpath() {
let mut classpath = Classpath::new();
assert_eq!(classpath.get_str(), String::new());
classpath.add("foo");
assert_eq!(classpath.get_str(), "foo".to_string());
classpath.add("bar");
assert_eq!(
classpath.get_str(),
"foo".to_string() + &CLASSPATH_SEP.to_string() + "bar"
);
}
#[test]
fn test_classpath_extension() {
let mut classpath = Classpath::new();
classpath.add("foo");
classpath.add("bar");
classpath.add("baz");
let mut classpath2 = Classpath::new();
classpath2.add("hello");
classpath2.add("world");
classpath.extend(classpath2);
assert_eq!(
classpath.get_str(),
format!("foo{0}bar{0}baz{0}hello{0}world", CLASSPATH_SEP)
);
}
}