diff options
| author | Valentin Popov <valentin@popov.link> | 2026-06-23 21:32:50 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-06-23 21:32:50 +0300 |
| commit | 9cc24e715db81edbe21c0d04aadd00f11dddecb8 (patch) | |
| tree | 08a1262dea86bcd7ec58c6494cedd001c45a78fe /crates/fparkan-inspection/src | |
| parent | f8e447ffee746cfe6580cc0e78a8a225aa39b546 (diff) | |
| download | fparkan-9cc24e715db81edbe21c0d04aadd00f11dddecb8.tar.xz fparkan-9cc24e715db81edbe21c0d04aadd00f11dddecb8.zip | |
fix: close stage 0-2 synthetic gates
Diffstat (limited to 'crates/fparkan-inspection/src')
| -rw-r--r-- | crates/fparkan-inspection/src/lib.rs | 75 |
1 files changed, 58 insertions, 17 deletions
diff --git a/crates/fparkan-inspection/src/lib.rs b/crates/fparkan-inspection/src/lib.rs index 0b35ad6..ac63bb9 100644 --- a/crates/fparkan-inspection/src/lib.rs +++ b/crates/fparkan-inspection/src/lib.rs @@ -1,21 +1,40 @@ #![forbid(unsafe_code)] +#![cfg_attr( + test, + allow( + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::expect_used, + clippy::float_cmp, + clippy::identity_op, + clippy::too_many_lines, + clippy::uninlined_format_args, + clippy::map_unwrap_or, + clippy::needless_raw_string_hashes, + clippy::semicolon_if_nothing_returned, + clippy::type_complexity, + clippy::panic, + clippy::unwrap_used + ) +)] //! Shared inspection helpers for format-backed tooling. use fparkan_msh::{decode_msh, validate_msh}; use fparkan_nres::{decode as decode_nres, NresDocument, ReadProfile}; -use fparkan_resource::{archive_path, resource_name, CachedResourceRepository}; +use fparkan_resource::{archive_path, resource_name, CachedResourceRepository, ResourceRepository}; use fparkan_rsli::decode as decode_rsli; use fparkan_terrain_format::{decode_land_map, decode_land_msh}; use fparkan_texm::decode_texm; -use fparkan_vfs::{DirectoryVfs, Vfs}; +use fparkan_vfs::DirectoryVfs; use std::fs; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::sync::Arc; /// Archive inspection variants. #[derive(Clone, Debug, Eq, PartialEq)] pub enum ArchiveInspection { - /// NRes inspection summary. + /// `NRes` inspection summary. Nres { /// Archive entry count. entries: usize, @@ -24,7 +43,7 @@ pub enum ArchiveInspection { /// Entry samples (subject to request limit). sample: Vec<NresEntrySummary>, }, - /// RsLi inspection summary. + /// `RsLi` inspection summary. Rsli { /// Archive entry count. entries: usize, @@ -33,7 +52,7 @@ pub enum ArchiveInspection { Unsupported, } -/// NRes entry summary. +/// `NRes` entry summary. #[derive(Clone, Debug, Eq, PartialEq)] pub struct NresEntrySummary { /// ASCII/legacy resource name. @@ -107,6 +126,10 @@ pub enum LandFileKind { } /// Inspects a format archive. +/// +/// # Errors +/// +/// Returns a string error when the archive cannot be read or decoded. pub fn inspect_archive_file(path: &Path, sample_limit: usize) -> Result<ArchiveInspection, String> { let bytes = fs::read(path).map_err(|err| format!("{}: {err}", path.display()))?; inspect_archive_bytes(&bytes, sample_limit, Some(path)) @@ -138,8 +161,11 @@ fn inspect_archive_bytes( sample, }) } else if bytes.get(0..4) == Some(b"NL\0\x01") { - let document = decode_rsli(Arc::from(bytes.to_vec().into_boxed_slice()), fparkan_rsli::ReadProfile::Compatible) - .map_err(|err| err.to_string())?; + let document = decode_rsli( + Arc::from(bytes.to_vec().into_boxed_slice()), + fparkan_rsli::ReadProfile::Compatible, + ) + .map_err(|err| err.to_string())?; Ok(ArchiveInspection::Rsli { entries: document.entries().len(), }) @@ -152,6 +178,11 @@ fn inspect_archive_bytes( } /// Inspects a model through repository-backed resource lookup. +/// +/// # Errors +/// +/// Returns a string error when the resource cannot be resolved or parsed as a +/// valid model payload. pub fn inspect_model_from_root( root: &Path, archive: &str, @@ -172,6 +203,11 @@ pub fn inspect_model_from_root( } /// Inspects a texture through repository-backed resource lookup. +/// +/// # Errors +/// +/// Returns a string error when the resource cannot be resolved or parsed as a +/// valid texture payload. pub fn inspect_texture_from_root( root: &Path, archive: &str, @@ -189,13 +225,15 @@ pub fn inspect_texture_from_root( } /// Inspects a terrain land file by path. +/// +/// # Errors +/// +/// Returns a string error when the file cannot be read or parsed as the +/// requested terrain payload kind. pub fn inspect_land_file(path: &Path, kind: LandFileKind) -> Result<MapInspection, String> { let bytes = fs::read(path).map_err(|err| format!("{}: {err}", path.display()))?; - let document = decode_nres( - Arc::from(bytes.into_boxed_slice()), - ReadProfile::Compatible, - ) - .map_err(|err| err.to_string())?; + let document = decode_nres(Arc::from(bytes.into_boxed_slice()), ReadProfile::Compatible) + .map_err(|err| err.to_string())?; match kind { LandFileKind::LandMsh => inspect_land_msh(&document), LandFileKind::LandMap => inspect_land_map(&document), @@ -254,17 +292,18 @@ fn read_resource_bytes(root: &Path, archive: &str, name: &str) -> Result<Arc<[u8 mod tests { use super::*; use std::io::Write as _; + use std::path::PathBuf; #[test] - fn inspect_rsli_counts_entries() { + fn inspect_rsli_rejects_malformed_archive() { let dir = temp_dir("inspect"); let path = dir.join("test.rsli"); let mut file = fs::File::create(&path).expect("file"); file.write_all(b"NL\0\x01").expect("magic"); drop(file); - let inspection = inspect_archive_file(&path, 0).expect("inspect"); - assert!(matches!(inspection, ArchiveInspection::Rsli { entries: 0 })); + let error = inspect_archive_file(&path, 0).expect_err("malformed archive"); + assert!(error.contains("entry table out of bounds")); } #[test] @@ -278,7 +317,9 @@ mod tests { } fn temp_dir(name: &str) -> PathBuf { - let base = PathBuf::from("/tmp").join("fparkan-inspection-tests").join(name); + let base = PathBuf::from("/tmp") + .join("fparkan-inspection-tests") + .join(name); let _ = fs::remove_dir_all(&base); fs::create_dir_all(&base).expect("tmp dir"); base |
