style: apply cargo fmt across workspace

This commit is contained in:
Karim Jerbi committed 2026-10-11 03:14:29 +01:00
1 parent 85710e5454
commit 9cf9ff2c5c
531 files changed
+57740 -33906

No files matched your search

+179 -181
View File
@@ -128,9 +128,9 @@ fn resolve_xrefs_with_filter(
.map(|(xref_index, (block_name, raw_path, br_handle))| {
let resolved = resolve_path(&raw_path, base_dir);
#[cfg(not(target_arch = "wasm32"))]
let initial_fingerprint = resolved.as_ref().and_then(|path| {
crate::io::edit_lock::FileFingerprint::capture(path).ok()
});
let initial_fingerprint = resolved
.as_ref()
.and_then(|path| crate::io::edit_lock::FileFingerprint::capture(path).ok());
#[cfg(target_arch = "wasm32")]
let initial_fingerprint = None;
let units = std::sync::Arc::clone(&parse_units);
@@ -217,8 +217,8 @@ fn resolve_xrefs_with_filter(
|| outcome.stats.skipped_source_records > 0
|| !outcome.stats.stream_completed
|| outcome.document.notifications.iter().any(|item| {
item.notification_type == codec::notification::NotificationType::Error
});
item.notification_type == codec::notification::NotificationType::Error
});
let mut diagnostics: Vec<String> = outcome
.document
.notifications
@@ -247,34 +247,29 @@ fn resolve_xrefs_with_filter(
if recovered || invalid > 0 {
(XrefStatus::Failed, diagnostics, Some(outcome.stats))
} else {
// Reload is replacement, never append. Keep the prior merge
// intact until parsing succeeded, then discard its generated
// entities, sortents, and dependent symbols immediately before
// importing the replacement content.
//
// VISRETAIN=1 (`header.retain_xref_visibility`): host-side
// layer overrides survive the purge — snapshot them first and
// re-apply onto the freshly merged layers below. Without this
// every reload silently reset frozen/off/color tweaks the
// user made on `name|*` layers back to file defaults.
let visretain = doc.header.retain_xref_visibility;
let kept_layers = if visretain {
snapshot_dependent_layers(doc, &block_name)
} else {
HashMap::default()
};
let _ = unload_reference(doc, br_handle.value());
remove_pipe_symbols(doc, &block_name);
ensure_block_entities(doc, &block_name);
dropped += merge_xref_into_block(
doc,
&block_name,
br_handle,
outcome.document,
);
if visretain {
restore_dependent_layers(doc, &block_name, kept_layers);
}
// Reload is replacement, never append. Keep the prior merge
// intact until parsing succeeded, then discard its generated
// entities, sortents, and dependent symbols immediately before
// importing the replacement content.
//
// VISRETAIN=1 (`header.retain_xref_visibility`): host-side
// layer overrides survive the purge — snapshot them first and
// re-apply onto the freshly merged layers below. Without this
// every reload silently reset frozen/off/color tweaks the
// user made on `name|*` layers back to file defaults.
let visretain = doc.header.retain_xref_visibility;
let kept_layers = if visretain {
snapshot_dependent_layers(doc, &block_name)
} else {
HashMap::default()
};
let _ = unload_reference(doc, br_handle.value());
remove_pipe_symbols(doc, &block_name);
ensure_block_entities(doc, &block_name);
dropped += merge_xref_into_block(doc, &block_name, br_handle, outcome.document);
if visretain {
restore_dependent_layers(doc, &block_name, kept_layers);
}
(XrefStatus::Loaded, diagnostics, Some(outcome.stats))
}
}
@@ -333,7 +328,10 @@ pub fn register_underlay_sources(doc: &CadDocument, base_dir: &Path) {
continue;
};
let stored = def.source_filename.trim();
if let Some(found) = (!stored.is_empty()).then(|| resolve_path(stored, base_dir)).flatten() {
if let Some(found) = (!stored.is_empty())
.then(|| resolve_path(stored, base_dir))
.flatten()
{
crate::scene::model::point_cloud::register_source(stored, found);
}
}
@@ -368,7 +366,8 @@ impl LayerLook {
/// The source file's layers by upper-case name, read once per file version.
fn source_layers(path: &Path) -> Option<HashMap<String, LayerLook>> {
type Cache = std::sync::Mutex<HashMap<PathBuf, (std::time::SystemTime, HashMap<String, LayerLook>)>>;
type Cache =
std::sync::Mutex<HashMap<PathBuf, (std::time::SystemTime, HashMap<String, LayerLook>)>>;
static CACHE: std::sync::OnceLock<Cache> = std::sync::OnceLock::new();
let modified = std::fs::metadata(path).and_then(|m| m.modified()).ok()?;
let cache = CACHE.get_or_init(Default::default);
@@ -545,16 +544,9 @@ impl BindTaken {
Self {
layers: upper_names(doc.layers.names().map(|s| s.to_string()).collect()),
linetypes: upper_names(doc.line_types.names().map(|s| s.to_string()).collect()),
text_styles: upper_names(
doc.text_styles.names().map(|s| s.to_string()).collect(),
),
text_styles: upper_names(doc.text_styles.names().map(|s| s.to_string()).collect()),
dim_styles: upper_names(doc.dim_styles.names().map(|s| s.to_string()).collect()),
blocks: upper_names(
doc.block_records
.iter()
.map(|b| b.name.clone())
.collect(),
),
blocks: upper_names(doc.block_records.iter().map(|b| b.name.clone()).collect()),
}
}
@@ -660,7 +652,9 @@ fn import_xref_symbols(
let same_file = doc
.text_styles
.iter()
.find(|host| host.is_shape_file && host.font_file.eq_ignore_ascii_case(&ts.font_file))
.find(|host| {
host.is_shape_file && host.font_file.eq_ignore_ascii_case(&ts.font_file)
})
.map(|host| host.handle);
if let Some(host_handle) = same_file {
maps.text_style_handles.insert(ts.handle, host_handle);
@@ -798,11 +792,7 @@ fn null_handle(handle: &mut Option<Handle>) -> usize {
/// Rewrite one entity's symbol references to the imported copies in place.
/// Returns the count of unremappable foreign handles (see
/// `bind_limitations` above) — ignored on the load path, reported per BIND.
fn remap_xref_entity(
host: &CadDocument,
entity: &mut EntityType,
maps: &XrefSymbolMaps,
) -> usize {
fn remap_xref_entity(host: &CadDocument, entity: &mut EntityType, maps: &XrefSymbolMaps) -> usize {
let mut unremapped = 0usize;
let rename = |map: &HashMap<String, String>, name: &mut String| {
if let Some(new) = map.get(&name.to_uppercase()) {
@@ -950,7 +940,8 @@ fn copy_xref_sortents(
nt.add_entry(ne, ns);
}
if !nt.is_empty() {
doc.objects.insert(nt.handle, ObjectType::SortEntitiesTable(nt));
doc.objects
.insert(nt.handle, ObjectType::SortEntitiesTable(nt));
}
}
}
@@ -1007,11 +998,16 @@ fn merge_xref_into_block(
// ── Entities (shared helper) ────────────────────────────────────────
// The unremapped-handle count is ignored on the load path (BIND reports
// it per bind).
let (dropped, _, entity_handle_map) =
merge_source_entities(doc, &xref_doc, br_handle, &maps);
let (dropped, _, entity_handle_map) = merge_source_entities(doc, &xref_doc, br_handle, &maps);
// ── Draw-order overrides (shared helper) ──────────────────────────────
copy_xref_sortents(doc, &xref_doc, br_handle, &maps.br_handles, &entity_handle_map);
copy_xref_sortents(
doc,
&xref_doc,
br_handle,
&maps.br_handles,
&entity_handle_map,
);
dropped
}
@@ -1152,11 +1148,11 @@ pub fn collect_entries_with_prev(
unloaded: &std::collections::HashSet<crate::io::xref_model::UnloadKey>,
prev: &std::collections::HashMap<u64, std::time::SystemTime>,
) -> Vec<crate::io::xref_model::ReferenceEntry> {
use codec::objects::ObjectType;
use crate::io::xref_model::{
child_key, decide_status, normalize_lexical, RefKind, RefStatus, RefType,
ReferenceEntry, UnloadKey,
child_key, decide_status, normalize_lexical, RefKind, RefStatus, RefType, ReferenceEntry,
UnloadKey,
};
use codec::objects::ObjectType;
/// Resolve `raw` via `base_dir`; on success record `found_at`, stat
/// size/mtime, and flip the entry to Loaded. Missing/empty stays NotFound.
@@ -1218,12 +1214,8 @@ pub fn collect_entries_with_prev(
resolve_only(&mut entry, &br.xref_path, base_dir);
} else {
stat_into(&mut entry, &br.xref_path, base_dir);
entry.status = decide_status(
entry.status,
entry.modified,
prev.get(&key).copied(),
false,
);
entry.status =
decide_status(entry.status, entry.modified, prev.get(&key).copied(), false);
}
entries.push(entry);
}
@@ -1253,12 +1245,8 @@ pub fn collect_entries_with_prev(
resolve_only(&mut entry, &def.file_name, base_dir);
} else {
stat_into(&mut entry, &def.file_name, base_dir);
entry.status = decide_status(
entry.status,
entry.modified,
prev.get(&key).copied(),
false,
);
entry.status =
decide_status(entry.status, entry.modified, prev.get(&key).copied(), false);
if is_unreferenced {
entry.status = RefStatus::Unreferenced;
}
@@ -1295,12 +1283,8 @@ pub fn collect_entries_with_prev(
resolve_only(&mut entry, &def.file_path, base_dir);
} else {
stat_into(&mut entry, &def.file_path, base_dir);
entry.status = decide_status(
entry.status,
entry.modified,
prev.get(&key).copied(),
false,
);
entry.status =
decide_status(entry.status, entry.modified, prev.get(&key).copied(), false);
if !referenced_underlays.contains(handle) {
entry.status = RefStatus::Unreferenced;
}
@@ -1326,7 +1310,12 @@ pub fn collect_entries_with_prev(
ObjectType::Dictionary(dictionary) => Some(dictionary),
_ => None,
})
.flat_map(|dictionary| dictionary.entries.iter().map(|(name, handle)| (*handle, name.clone())))
.flat_map(|dictionary| {
dictionary
.entries
.iter()
.map(|(name, handle)| (*handle, name.clone()))
})
.collect();
for (handle, obj) in doc.objects.iter() {
let ObjectType::ClassObject(object) = obj else {
@@ -1349,7 +1338,8 @@ pub fn collect_entries_with_prev(
resolve_only(&mut entry, &def.source_filename, base_dir);
} else {
stat_into(&mut entry, &def.source_filename, base_dir);
entry.status = decide_status(entry.status, entry.modified, prev.get(&key).copied(), false);
entry.status =
decide_status(entry.status, entry.modified, prev.get(&key).copied(), false);
if !referenced_clouds.contains(handle) {
entry.status = RefStatus::Unreferenced;
}
@@ -1395,7 +1385,11 @@ pub fn collect_entries_with_prev(
let key = child_key(parent_key, &br.name, &br.xref_path);
let mut child = ReferenceEntry::new(key, br.name.clone(), RefKind::DwgXref);
child.parent_key = Some(parent_key);
child.ref_type = if br.flags.is_xref_overlay { RefType::Overlay } else { RefType::Attach };
child.ref_type = if br.flags.is_xref_overlay {
RefType::Overlay
} else {
RefType::Attach
};
child.saved_path = br.xref_path.clone();
if unloaded.contains(&UnloadKey::Nested(key)) {
child.status = RefStatus::Unloaded;
@@ -1404,7 +1398,8 @@ pub fn collect_entries_with_prev(
// Nested baselines live in the same stat cache under the
// child's high-bit-tagged key, which can never alias a host
// handle (see `child_key`) — so the lookup below is safe.
child.status = decide_status(child.status, child.modified, prev.get(&key).copied(), false);
child.status =
decide_status(child.status, child.modified, prev.get(&key).copied(), false);
}
if let Some(found) = &child.found_at {
let resolved_id = normalize_lexical(found);
@@ -1422,8 +1417,11 @@ pub fn collect_entries_with_prev(
// reaches a parent, the parent already reflects its own subtree.
// Unloaded/NotFound/Failed rows are never overridden.
{
let index: HashMap<u64, usize> =
entries.iter().enumerate().map(|(i, e)| (e.key, i)).collect();
let index: HashMap<u64, usize> = entries
.iter()
.enumerate()
.map(|(i, e)| (e.key, i))
.collect();
for rev in (0..entries.len()).rev() {
if entries[rev].status != RefStatus::Stale {
continue;
@@ -1472,7 +1470,10 @@ fn find_target(doc: &CadDocument, key: u64) -> Option<RefTarget> {
}
ObjectType::ClassObject(object) if handle.value() == key => {
if let codec::objects::ClassObjectData::PointCloudDefinitionEx(def) = &object.data {
return Some(RefTarget::PointCloud { handle: *handle, name: def.source_filename.clone() });
return Some(RefTarget::PointCloud {
handle: *handle,
name: def.source_filename.clone(),
});
}
}
ObjectType::UnderlayDefinition(def) if handle.value() == key => {
@@ -1524,9 +1525,7 @@ pub fn unload_reference(doc: &mut CadDocument, key: u64) -> Result<String, Strin
.objects
.iter()
.filter_map(|(h, o)| match o {
ObjectType::SortEntitiesTable(t)
if t.block_owner_handle == handle =>
{
ObjectType::SortEntitiesTable(t) if t.block_owner_handle == handle => {
Some(*h)
}
_ => None,
@@ -1585,9 +1584,7 @@ pub fn detach_reference(doc: &mut CadDocument, key: u64) -> Result<String, Strin
let inserts: Vec<Handle> = doc
.entities()
.filter_map(|e| match e {
EntityType::Insert(ins)
if ins.block_name.eq_ignore_ascii_case(&name) =>
{
EntityType::Insert(ins) if ins.block_name.eq_ignore_ascii_case(&name) => {
Some(e.common().handle)
}
_ => None,
@@ -1614,9 +1611,7 @@ pub fn detach_reference(doc: &mut CadDocument, key: u64) -> Result<String, Strin
.objects
.iter()
.filter_map(|(h, o)| match o {
ObjectType::SortEntitiesTable(t)
if t.block_owner_handle == handle =>
{
ObjectType::SortEntitiesTable(t) if t.block_owner_handle == handle => {
Some(*h)
}
_ => None,
@@ -1633,9 +1628,7 @@ pub fn detach_reference(doc: &mut CadDocument, key: u64) -> Result<String, Strin
let refs: Vec<Handle> = doc
.entities()
.filter_map(|e| match e {
EntityType::RasterImage(img)
if img.definition_handle == Some(handle) =>
{
EntityType::RasterImage(img) if img.definition_handle == Some(handle) => {
Some(e.common().handle)
}
_ => None,
@@ -1671,7 +1664,9 @@ pub fn detach_reference(doc: &mut CadDocument, key: u64) -> Result<String, Strin
.entities()
.filter_map(|e| match e {
EntityType::Extended(extended) => match &extended.data {
ExtendedEntityData::PointCloudEx(data) if data.definition_handle == handle => {
ExtendedEntityData::PointCloudEx(data)
if data.definition_handle == handle =>
{
Some((e.common().handle, data.reactor_handle))
}
_ => None,
@@ -1733,7 +1728,10 @@ pub fn bind_reference(
RefTarget::DwgXref { handle, name } => bind_dwg(doc, handle, &name, base_dir, host_dir),
RefTarget::Image { handle, name } => {
collect_bind_images(doc, &name, base_dir, host_dir, Some(handle))?;
Ok(BindOutcome { name, unremapped: 0 })
Ok(BindOutcome {
name,
unremapped: 0,
})
}
RefTarget::Pdf { .. } => Err(crate::t!(
"XREF: PDF bind (vector import) is not available in this version."
@@ -1811,14 +1809,14 @@ fn load_bind_source(ref_name: &str, found: &Path) -> Result<CadDocument, String>
fn check_no_pdf_underlays(source: &CadDocument) -> Result<(), String> {
use codec::entities::UnderlayType;
use codec::objects::ObjectType;
let has_pdf = source.objects.values().any(|o| {
matches!(o, ObjectType::UnderlayDefinition(d) if d.underlay_type == UnderlayType::Pdf)
});
let has_pdf = source.objects.values().any(
|o| matches!(o, ObjectType::UnderlayDefinition(d) if d.underlay_type == UnderlayType::Pdf),
);
if has_pdf {
return Err(crate::t!(
"XREF: PDF bind (vector import) is not available in this version."
)
.to_string());
return Err(
crate::t!("XREF: PDF bind (vector import) is not available in this version.")
.to_string(),
);
}
Ok(())
}
@@ -1845,8 +1843,7 @@ fn bind_nested_closure(
let Some(child_found) = resolve_path(&child_saved, source_dir) else {
return Err(bind_failed(&child_name, "file not found"));
};
let norm =
crate::io::xref_model::normalize_lexical(&child_found.to_string_lossy());
let norm = crate::io::xref_model::normalize_lexical(&child_found.to_string_lossy());
if stack.contains(&norm) {
continue;
}
@@ -1926,9 +1923,7 @@ fn collect_bind_images(
.objects
.iter()
.filter_map(|(h, o)| match o {
ObjectType::ImageDefinition(d)
if only.is_none_or(|want| want == *h) =>
{
ObjectType::ImageDefinition(d) if only.is_none_or(|want| want == *h) => {
Some((*h, d.file_name.clone()))
}
_ => None,
@@ -2018,11 +2013,7 @@ pub const POINT_CLOUD_KEY: &str = "pointcloud:";
/// Make the named references' paths relative to `host` (their drawing's
/// first save); a reference that cannot be relative keeps its full path.
pub fn make_relative(
doc: &mut CadDocument,
names: &rustc_hash::FxHashSet<String>,
host: &Path,
) {
pub fn make_relative(doc: &mut CadDocument, names: &rustc_hash::FxHashSet<String>, host: &Path) {
for name in names {
if let Some(handle) = name.strip_prefix(POINT_CLOUD_KEY) {
if let Ok(handle) = u64::from_str_radix(handle, 16) {
@@ -2232,10 +2223,7 @@ fn restore_dependent_layers(
.map(|s| s.to_string())
.collect();
for n in targets {
let (Some(cur), Some(old)) = (
doc.layers.get_mut(&n),
kept.get(&n.to_uppercase()),
) else {
let (Some(cur), Some(old)) = (doc.layers.get_mut(&n), kept.get(&n.to_uppercase())) else {
continue;
};
cur.flags = old.flags.clone();
@@ -2251,11 +2239,7 @@ fn restore_dependent_layers(
}
/// Store `new_raw` verbatim on the definition (no synthesis).
pub fn set_ref_path(
doc: &mut CadDocument,
key: u64,
new_raw: &str,
) -> Result<String, String> {
pub fn set_ref_path(doc: &mut CadDocument, key: u64, new_raw: &str) -> Result<String, String> {
let Some(target) = find_target(doc, key) else {
return Err(crate::t!("XREF: no loaded reference with that key.").to_string());
};
@@ -2359,9 +2343,10 @@ pub fn apply_pathtype(
Err(crate::io::xref_model::PathtypeError::AcrossDrives) => {
Err(crate::t!("XREF: cannot make path relative across drives.").to_string())
}
Err(crate::io::xref_model::PathtypeError::UnsavedHost) => Err(
crate::t!("XREF Save the drawing first to resolve relative XREF paths.").to_string(),
),
Err(crate::io::xref_model::PathtypeError::UnsavedHost) => Err(crate::t!(
"XREF Save the drawing first to resolve relative XREF paths."
)
.to_string()),
}
}
@@ -2539,9 +2524,9 @@ mod tests {
use super::collect_entries_with_prev;
use super::HashSet;
use super::{
apply_pathtype, child_key, detach_reference, replace_path_prefix,
resolve_xrefs_for_keys, restore_dependent_layers, set_ref_path,
set_ref_type, snapshot_dependent_layers, unload_reference,
apply_pathtype, child_key, detach_reference, replace_path_prefix, resolve_xrefs_for_keys,
restore_dependent_layers, set_ref_path, set_ref_type, snapshot_dependent_layers,
unload_reference,
};
use crate::io::xref_model::{Pathtype, RefKind, RefStatus, RefType};
@@ -2624,26 +2609,21 @@ mod tests {
use std::time::UNIX_EPOCH;
let dir = xref_tmpdir("staleprop");
let (mid_path, inner_path) = write_nested_fixture(&dir);
let (doc, mid_key) = xref_doc_with(
"MID",
&mid_path.to_string_lossy(),
);
let inner_key = child_key(
mid_key,
"INNER",
&inner_path.to_string_lossy(),
);
let (doc, mid_key) = xref_doc_with("MID", &mid_path.to_string_lossy());
let inner_key = child_key(mid_key, "INNER", &inner_path.to_string_lossy());
let mut prev = std::collections::HashMap::new();
prev.insert(inner_key, UNIX_EPOCH);
let entries = collect_entries_with_prev(
&doc,
&dir,
&std::collections::HashSet::new(),
&prev,
);
let inner = entries.iter().find(|e| e.key == inner_key).expect("nested INNER listed");
let entries =
collect_entries_with_prev(&doc, &dir, &std::collections::HashSet::new(), &prev);
let inner = entries
.iter()
.find(|e| e.key == inner_key)
.expect("nested INNER listed");
assert_eq!(inner.status, RefStatus::Stale);
let mid = entries.iter().find(|e| e.key == mid_key).expect("MID listed");
let mid = entries
.iter()
.find(|e| e.key == mid_key)
.expect("MID listed");
assert_eq!(mid.status, RefStatus::Stale, "parent reflects stale child");
std::fs::remove_dir_all(&dir).ok();
}
@@ -2658,49 +2638,61 @@ mod tests {
let dir = xref_tmpdir("e2e");
let (mid_path, _) = write_nested_fixture(&dir);
std::fs::write(dir.join("img.png"), b"fake-png").unwrap();
let (mut doc, mid_key) =
xref_doc_with("MID", &mid_path.to_string_lossy());
let (mut doc, mid_key) = xref_doc_with("MID", &mid_path.to_string_lossy());
// Referenced image → Loaded entry.
let img_h = doc.allocate_handle();
let mut img_def = ImageDefinition::with_dimensions("img.png", 8, 8);
img_def.handle = img_h;
doc.objects.insert(img_h, ObjectType::ImageDefinition(img_def));
let mut img = codec::entities::RasterImage::new(
"img.png",
codec::types::Vector3::ZERO,
8.0,
8.0,
);
doc.objects
.insert(img_h, ObjectType::ImageDefinition(img_def));
let mut img =
codec::entities::RasterImage::new("img.png", codec::types::Vector3::ZERO, 8.0, 8.0);
img.definition_handle = Some(img_h);
doc.add_entity(codec::EntityType::RasterImage(img)).unwrap();
// Unreferenced PDF definition → listed, never merged.
let pdf_h = doc.allocate_handle();
let mut pdf_def = UnderlayDefinition::pdf("doc.pdf", "1");
pdf_def.handle = pdf_h;
doc.objects.insert(pdf_h, ObjectType::UnderlayDefinition(pdf_def));
doc.objects
.insert(pdf_h, ObjectType::UnderlayDefinition(pdf_def));
let empty = std::collections::HashSet::new();
let no_prev = std::collections::HashMap::new();
// 1. List: everything visible with the right statuses.
let listed = collect_entries_with_prev(&doc, &dir, &empty, &no_prev);
assert!(listed.iter().any(|e| e.name == "MID" && e.status == RefStatus::Loaded));
assert!(listed.iter().any(|e| e.name == "INNER" && e.parent_key.is_some()));
assert!(listed.iter().any(|e| e.name == "img.png" && e.status == RefStatus::Loaded));
assert!(listed.iter().any(|e| e.name == "doc.pdf" && e.status == RefStatus::Unreferenced));
assert!(listed
.iter()
.any(|e| e.name == "MID" && e.status == RefStatus::Loaded));
assert!(listed
.iter()
.any(|e| e.name == "INNER" && e.parent_key.is_some()));
assert!(listed
.iter()
.any(|e| e.name == "img.png" && e.status == RefStatus::Loaded));
assert!(listed
.iter()
.any(|e| e.name == "doc.pdf" && e.status == RefStatus::Unreferenced));
// 2. Unload: definition retained, content marked.
unload_reference(&mut doc, mid_key).expect("unload");
let mut unloaded = std::collections::HashSet::new();
unloaded.insert(crate::io::xref_model::UnloadKey::Direct(mid_key));
let listed = collect_entries_with_prev(&doc, &dir, &unloaded, &no_prev);
assert!(listed.iter().any(|e| e.name == "MID" && e.status == RefStatus::Unloaded));
assert!(doc.block_records.get("MID").is_some(), "definition retained");
assert!(listed
.iter()
.any(|e| e.name == "MID" && e.status == RefStatus::Unloaded));
assert!(
doc.block_records.get("MID").is_some(),
"definition retained"
);
// 3. Targeted reload: back to Loaded.
let mut handles = HashSet::default();
handles.insert(doc.block_records.get("MID").unwrap().handle);
let (infos, _) = resolve_xrefs_for_keys(&mut doc, &dir, &handles);
assert!(infos.iter().any(|i| i.name == "MID"));
let listed = collect_entries_with_prev(&doc, &dir, &empty, &no_prev);
assert!(listed.iter().any(|e| e.name == "MID" && e.status == RefStatus::Loaded));
assert!(listed
.iter()
.any(|e| e.name == "MID" && e.status == RefStatus::Loaded));
// 4. Detach: instances, definition, and nested rows all gone.
detach_reference(&mut doc, mid_key).expect("detach");
let listed = collect_entries_with_prev(&doc, &dir, &empty, &no_prev);
@@ -2776,7 +2768,10 @@ mod tests {
line.common.handle = codec::types::Handle::NULL;
line.common.owner_handle = br_h;
doc.add_entity(codec::EntityType::Line(line)).unwrap();
assert_eq!(doc.block_records.get("PLAN").unwrap().entity_handles.len(), 1);
assert_eq!(
doc.block_records.get("PLAN").unwrap().entity_handles.len(),
1
);
unload_reference(&mut doc, key).expect("unload");
assert!(doc.block_records.get("PLAN").is_some());
let owned: Vec<_> = doc
@@ -2814,7 +2809,8 @@ mod tests {
assert!(kept.contains_key("PLAN|WALLS"));
// Simulate the purge + file-default re-merge.
doc.layers.remove("PLAN|WALLS");
doc.layers.add_or_replace(codec::tables::Layer::new("PLAN|WALLS"));
doc.layers
.add_or_replace(codec::tables::Layer::new("PLAN|WALLS"));
assert!(!doc.layers.get("PLAN|WALLS").unwrap().flags.off);
restore_dependent_layers(&mut doc, "PLAN", kept);
let back = doc.layers.get("PLAN|WALLS").unwrap();
@@ -2883,10 +2879,7 @@ mod tests {
let (mut doc, _) = xref_doc_with("PLAN", "aé/x.dwg");
let n = replace_path_prefix(&mut doc, "a/", "q/");
assert_eq!(n, 0);
assert_eq!(
doc.block_records.get("PLAN").unwrap().xref_path,
"aé/x.dwg"
);
assert_eq!(doc.block_records.get("PLAN").unwrap().xref_path, "aé/x.dwg");
let (mut doc2, _) = xref_doc_with("PLAN", "répértoire/old/plan.dwg");
let n2 = replace_path_prefix(&mut doc2, "répértoire/old", "répértoire/new");
assert_eq!(n2, 1);
@@ -3029,7 +3022,10 @@ mod tests {
assert_eq!(outcome.name, "PLAN");
assert!(host.layers.get("PLAN$0$DETAIL$0$WALLS").is_some());
assert!(host.layers.get("PLAN$0$PLANLAYER").is_some());
let child = host.block_records.get("PLAN$0$DETAIL").expect("bound child block");
let child = host
.block_records
.get("PLAN$0$DETAIL")
.expect("bound child block");
assert!(!child.flags.is_xref && !child.flags.is_xref_overlay);
assert!(!host
.block_records
@@ -3052,10 +3048,7 @@ mod tests {
inner.common.layer = "WALLS".to_string();
inner.common.owner_handle = door_h;
doc.add_entity(codec::EntityType::Line(inner)).unwrap();
let ins = codec::entities::Insert::new(
"DOOR",
codec::types::Vector3::ZERO,
);
let ins = codec::entities::Insert::new("DOOR", codec::types::Vector3::ZERO);
doc.add_entity(codec::EntityType::Insert(ins)).unwrap();
// Hatch (pattern names have no table — preserved verbatim).
let mut hatch = codec::entities::Hatch::new();
@@ -3091,8 +3084,7 @@ mod tests {
let hatches: Vec<_> = host
.entities()
.filter(|e| {
e.common().owner_handle == br.handle
&& matches!(e, codec::EntityType::Hatch(_))
e.common().owner_handle == br.handle && matches!(e, codec::EntityType::Hatch(_))
})
.collect();
assert_eq!(hatches.len(), 1);
@@ -3146,8 +3138,7 @@ mod tests {
let lines: Vec<_> = host
.entities()
.filter(|e| {
e.common().owner_handle == br.handle
&& matches!(e, codec::EntityType::Line(_))
e.common().owner_handle == br.handle && matches!(e, codec::EntityType::Line(_))
})
.collect();
assert_eq!(lines.len(), 1);
@@ -3238,9 +3229,13 @@ mod tests {
let mut def = UnderlayDefinition::pdf("doc.pdf", "1");
def.handle = h;
host.objects.insert(h, ObjectType::UnderlayDefinition(def));
let err =
bind_reference(&mut host, h.value(), std::path::Path::new("."), std::path::Path::new("."))
.unwrap_err();
let err = bind_reference(
&mut host,
h.value(),
std::path::Path::new("."),
std::path::Path::new("."),
)
.unwrap_err();
assert_eq!(
err,
"XREF: PDF bind (vector import) is not available in this version."
@@ -3275,7 +3270,10 @@ fn relative_point_cloud_path(doc: &mut CadDocument, handle: Handle, host: &Path)
};
if let Ok(relative) = to_pathtype_result(&def.source_filename, host, Pathtype::Relative) {
let relative = relative.replace('/', "\\");
if let Some(found) = std::path::Path::new(&def.source_filename).is_file().then(|| def.source_filename.clone()) {
if let Some(found) = std::path::Path::new(&def.source_filename)
.is_file()
.then(|| def.source_filename.clone())
{
crate::scene::model::point_cloud::register_source(&relative, found.into());
}
def.source_filename = relative;