Files
raven/retired/nest_lib_rs_old/class.rs
2026-02-15 09:36:04 -05:00

115 lines
3.1 KiB
Rust

use std::hash::{self, Hash};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use crate::{Error, Result};
use java::{JAVA_EXT_CLASS, JAVA_EXT_SOURCE};
use path::PathHandler;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Class {
#[serde(skip_deserializing, skip_serializing)]
ph: Option<Arc<Mutex<PathHandler>>>,
path: PathBuf,
checksum: String,
}
impl Class {
pub fn new<P: AsRef<Path>>(ph: Arc<Mutex<PathHandler>>, path: P, checksum: String) -> Self {
Self {
ph: Some(ph),
path: path.as_ref().to_path_buf(),
checksum,
}
}
pub fn from_file<P: AsRef<Path>>(ph: Arc<Mutex<PathHandler>>, path: P) -> Result<Self> {
let mut path = path.as_ref().to_path_buf();
if path.is_relative() {
path = path.canonicalize()?;
}
let dir_src = ph.try_lock()?.dir_src();
Ok(Self {
ph: Some(ph),
path: PathBuf::from(
pathsub::sub_paths(path.as_path(), dir_src.as_path()).ok_or(Error::PathSub)?,
)
.with_extension(""),
checksum: sha256::try_digest(&path)?,
})
}
pub fn path(&self) -> PathBuf {
self.path.clone()
}
pub fn checksum(&self) -> String {
self.checksum.clone()
}
/// Returns the path such that src/ and target/ don't matter.
/// E.g., `main/Main.java` as_subpath is `Main.java`
/// allowing it to match with `target/main/Main.class`
/// because Java diregards the top level subdir in `src/`
fn subpath(&self) -> PathBuf {
let mut p = self.path.components();
p.next(); // Remove the top level dir.
p.as_path().to_path_buf()
}
/// Returns true if the class needs updating.
/// This may also cautionarily return true if it cannot digest the file.
pub fn is_updated(&mut self) -> Result<bool> {
// Still doesn't handle inter-dependency checks.
// Hopefully then I'll clean this horror up.
let mut ph = self
.ph
.as_ref()
.ok_or(Error::MissingPathHandler)?
.try_lock()?;
Ok(ph
.dir_target()
.join(self.subpath())
.with_extension(JAVA_EXT_CLASS)
.exists()
&& sha256::try_digest(
ph.dir_src()
.join(self.path())
.with_extension(JAVA_EXT_SOURCE),
)
.is_ok_and(|hash| self.checksum == hash))
}
pub fn set_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) {
self.ph = Some(ph);
}
pub fn with_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) -> &mut Self {
self.ph = Some(ph);
self
}
}
impl Hash for Class {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.path.hash(state);
}
}
impl PartialEq for Class {
fn eq(&self, other: &Self) -> bool {
self.path == other.path
}
fn ne(&self, other: &Self) -> bool {
self.path != other.path
}
}
impl Eq for Class {}