use crate::module::descriptor::ModuleDescriptor;
use std::fmt;
use std::path::PathBuf;
use std::sync::Arc;
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum ModuleSource {
System,
Upgrade,
ModulePath,
Automatic,
Synthetic,
}
#[derive(Clone, Debug)]
pub struct ModuleReference {
descriptor: Arc<ModuleDescriptor>,
source: ModuleSource,
location: Option<PathBuf>,
is_automatic: bool,
}
impl ModuleReference {
#[must_use]
pub fn new(
descriptor: ModuleDescriptor,
source: ModuleSource,
location: Option<PathBuf>,
) -> Self {
let is_automatic = matches!(source, ModuleSource::Automatic);
Self {
descriptor: Arc::new(descriptor),
source,
location,
is_automatic,
}
}
#[must_use]
pub fn system(descriptor: ModuleDescriptor) -> Self {
Self::new(descriptor, ModuleSource::System, None)
}
#[must_use]
pub fn automatic(descriptor: ModuleDescriptor, location: PathBuf) -> Self {
Self::new(descriptor, ModuleSource::Automatic, Some(location))
}
#[must_use]
pub fn descriptor(&self) -> &ModuleDescriptor {
&self.descriptor
}
#[must_use]
pub fn name(&self) -> &str {
&self.descriptor.name
}
#[must_use]
pub fn source(&self) -> &ModuleSource {
&self.source
}
#[must_use]
pub fn location(&self) -> Option<&PathBuf> {
self.location.as_ref()
}
#[must_use]
pub fn is_automatic(&self) -> bool {
self.is_automatic
}
#[must_use]
pub fn is_system(&self) -> bool {
matches!(self.source, ModuleSource::System)
}
}
impl fmt::Display for ModuleReference {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.descriptor)?;
if let Some(ref loc) = self.location {
write!(f, " ({})", loc.display())?;
}
Ok(())
}
}
impl PartialEq for ModuleReference {
fn eq(&self, other: &Self) -> bool {
self.descriptor.name == other.descriptor.name && self.source == other.source
}
}
impl Eq for ModuleReference {}
impl std::hash::Hash for ModuleReference {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.descriptor.name.hash(state);
self.source.hash(state);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_module_reference() {
let descriptor = ModuleDescriptor::new("test.module".to_string());
let reference = ModuleReference::system(descriptor);
assert_eq!(reference.name(), "test.module");
assert!(reference.is_system());
assert!(!reference.is_automatic());
}
#[test]
fn test_automatic_module_reference() {
let descriptor = ModuleDescriptor::new("automatic.module".to_string());
let reference = ModuleReference::automatic(descriptor, PathBuf::from("test.jar"));
assert_eq!(reference.name(), "automatic.module");
assert!(!reference.is_system());
assert!(reference.is_automatic());
}
}