201 lines
4.6 KiB
Rust
201 lines
4.6 KiB
Rust
use std::error::Error;
|
|
use std::fmt::{Display, Formatter};
|
|
use std::path::PathBuf;
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
|
pub struct FileNameInfo {
|
|
pub name: String,
|
|
pub version: Option<String>,
|
|
pub extension: Option<String>,
|
|
}
|
|
|
|
impl FileNameInfo {
|
|
pub fn to_full_file_name(&self) -> String {
|
|
self.to_string()
|
|
}
|
|
}
|
|
|
|
impl TryFrom<PathBuf> for FileNameInfo {
|
|
type Error = FileInfoError;
|
|
|
|
fn try_from(file: PathBuf) -> Result<Self, Self::Error> {
|
|
if !file.is_file() {
|
|
return Err(FileInfoError::NotAFile);
|
|
}
|
|
|
|
let file_name = file.file_name().ok_or(FileInfoError::NotAFile)?;
|
|
let file_name = file_name
|
|
.to_str()
|
|
.ok_or(FileInfoError::InvalidCharactersInFileName)?;
|
|
|
|
let (file_name_without_version, extension) =
|
|
match file_name.rsplit_once('.').filter(|(_, ending)| {
|
|
ending.parse::<u32>().is_err() //there are usually no file extensions which are just a number, but rather versions
|
|
}) {
|
|
Some((name, ending)) => (name, Some(ending.to_string())),
|
|
None => (file_name, None),
|
|
};
|
|
|
|
let (name, version) = match file_name_without_version.split_once('-') {
|
|
Some((name, version)) => (name, Some(version.to_string())),
|
|
None => (file_name_without_version, None),
|
|
};
|
|
|
|
Ok(Self {
|
|
name: name.to_string(),
|
|
version,
|
|
extension,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Display for FileNameInfo {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}{}{}",
|
|
self.name,
|
|
self
|
|
.version
|
|
.as_ref()
|
|
.map(|v| format!("-{v}"))
|
|
.unwrap_or_default(),
|
|
self
|
|
.extension
|
|
.as_ref()
|
|
.map(|extension| format!(".{extension}"))
|
|
.unwrap_or_default()
|
|
)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum FileInfoError {
|
|
NotAFile,
|
|
InvalidCharactersInFileName,
|
|
}
|
|
|
|
impl Display for FileInfoError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
FileInfoError::NotAFile => write!(f, "Path doesn't point to a file"),
|
|
FileInfoError::InvalidCharactersInFileName => write!(f, "Invalid characters in file name"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Error for FileInfoError {}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct FileMatcher {
|
|
name: String,
|
|
extension: Option<String>,
|
|
}
|
|
|
|
impl FileMatcher {
|
|
pub fn from<S>(name: S) -> Self
|
|
where
|
|
S: ToString,
|
|
{
|
|
Self {
|
|
name: name.to_string(),
|
|
extension: None,
|
|
}
|
|
}
|
|
|
|
pub fn and_extension<S>(self, extension: S) -> Self
|
|
where
|
|
S: ToString,
|
|
{
|
|
Self {
|
|
extension: Some(extension.to_string()),
|
|
..self
|
|
}
|
|
}
|
|
|
|
pub fn matches(&self, file_name: &str) -> bool {
|
|
file_name.starts_with(&self.name)
|
|
&& self
|
|
.extension
|
|
.as_ref()
|
|
.is_none_or(|extension| file_name.ends_with(extension))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test_file_name_info {
|
|
use crate::file::FileNameInfo;
|
|
use std::path::PathBuf;
|
|
|
|
#[test]
|
|
fn test_from_plugin() {
|
|
assert_eq!(
|
|
FileNameInfo {
|
|
name: "TestPlugin".to_string(),
|
|
version: Some("1.0.0".to_string()),
|
|
extension: Some("jar".to_string()),
|
|
},
|
|
FileNameInfo::try_from(PathBuf::from("test-ressources/files/TestPlugin-1.0.0.jar"))
|
|
.expect("valid file")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_from_unversioned() {
|
|
assert_eq!(
|
|
FileNameInfo {
|
|
name: "unversioned".to_string(),
|
|
version: None,
|
|
extension: Some("jar".to_string()),
|
|
},
|
|
FileNameInfo::try_from(PathBuf::from("test-ressources/files/unversioned.jar"))
|
|
.expect("valid file")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_from_versioned_bin() {
|
|
assert_eq!(
|
|
FileNameInfo {
|
|
name: "bin".to_string(),
|
|
version: Some("7.3".to_string()),
|
|
extension: None,
|
|
},
|
|
FileNameInfo::try_from(PathBuf::from("test-ressources/files/bin-7.3")).expect("valid file")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_from_unversioned_bin() {
|
|
assert_eq!(
|
|
FileNameInfo {
|
|
name: "test".to_string(),
|
|
version: None,
|
|
extension: None,
|
|
},
|
|
FileNameInfo::try_from(PathBuf::from("test-ressources/files/test")).expect("valid file")
|
|
);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test_file_matcher {
|
|
use crate::file::FileMatcher;
|
|
|
|
#[test]
|
|
fn test_match_with_extension() {
|
|
let matcher = FileMatcher::from("test").and_extension(".jar");
|
|
assert!(matcher.matches("test.jar"));
|
|
assert!(matcher.matches("test-1.3.0.jar"));
|
|
assert!(!matcher.matches("test"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_match_without_extension() {
|
|
let matcher = FileMatcher::from("test");
|
|
assert!(matcher.matches("test.jar"));
|
|
assert!(matcher.matches("test-1.3.0.jar"));
|
|
assert!(matcher.matches("test"));
|
|
}
|
|
}
|