use crate::prelude::*;
#[injectable]
pub(crate) struct FlacVerifier {
paths: Ref<PathManager>,
}
impl FlacVerifier {
pub(crate) fn execute(
&self,
source: &Source,
flacs: &[FlacFile],
) -> Result<Vec<SourceIssue>, Failure<VerifyAction>> {
trace!("{} {} FLACs", "Checking".bold(), flacs.len());
let mut issues: Vec<SourceIssue> = Vec::new();
issues.extend(check_flac_count(source, flacs.len()));
issues.extend(check_subdirectory(flacs));
let max_target = get_max_path_length_target(source);
let output_dir = self.paths.get_output_dir();
for flac in flacs {
if let Some(max_target) = max_target {
let path = self
.paths
.get_transcode_path(source, max_target, flac)
.strip_prefix(output_dir.clone())
.expect("should be able to strip prefix from transcode path")
.to_path_buf();
issues.extend(check_path_length(&path));
}
let tag_issues = TagVerifier::execute(flac, source)
.map_err(Failure::wrap(VerifyAction::VerifyTags))?;
issues.extend(tag_issues);
issues.extend(StreamVerifier::execute(flac, source));
}
Ok(issues)
}
}
pub(crate) fn check_flac_count(source: &Source, actual: usize) -> Option<SourceIssue> {
let expected = source.torrent.get_flacs().len();
if actual != expected {
return Some(SourceIssue::FlacCount { expected, actual });
}
None
}
pub(crate) fn check_subdirectory(flacs: &[FlacFile]) -> Option<SourceIssue> {
let flac_sub_dirs: Vec<_> = flacs.iter().map(|x| &x.sub_dir).collect();
Shortener::longest_common_prefix(&flac_sub_dirs)
.map(|prefix| SourceIssue::UnnecessaryDirectory { prefix })
}
fn get_max_path_length_target(source: &Source) -> Option<TargetFormat> {
source.targets.first().copied()
}
#[expect(
clippy::cast_sign_loss,
clippy::cast_possible_wrap,
clippy::as_conversions,
reason = "bounded path length"
)]
pub(crate) fn check_path_length(path: &Path) -> Option<SourceIssue> {
let length = path.to_string_lossy().chars().count() as isize;
let excess = length - MAX_PATH_LENGTH;
if excess > 0 {
return Some(SourceIssue::Length {
path: path.to_path_buf(),
excess: excess as usize,
});
}
None
}