chore: expose lib target + open-path profiling examples

Examples can't import from a bin-only crate, so add a thin lib.rs that
re-exports the existing modules. Used by the new examples that helped
diagnose the freeze fixed in the previous commit.

- examples/time_open: times parse / purge / cache / first-wires phases
- examples/inspect_insert: lists Insert blocks with sub-entity counts
- examples/find_raster: dumps RasterImage path + dimensions

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.7 committed 2026-05-13 23:02:54 +03:00
1 parent c61d648dc7
commit 03555ce8bd
4 files changed
+154

No files matched your search

+14
View File
@@ -0,0 +1,14 @@
use acadrust::entities::EntityType;
use acadrust::io::dwg::DwgReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let path = std::env::args().nth(1).unwrap();
let doc = DwgReader::from_file(&path)?.read()?;
for e in doc.entities() {
if let EntityType::RasterImage(img) = e {
println!("file_path: {}", img.file_path);
println!("size: {} x {}", img.size.x, img.size.y);
if let Ok(meta) = std::fs::metadata(&img.file_path) { println!("disk size: {} bytes", meta.len()); }
}
}
Ok(())
}
+43
View File
@@ -0,0 +1,43 @@
// Lists every Insert in the doc (after xref resolve) with sub-entity counts.
// cargo run --release --example inspect_insert -- <dwg>
use acadrust::entities::EntityType;
use acadrust::io::dwg::DwgReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let path = std::env::args().nth(1).unwrap();
let mut doc = DwgReader::from_file(&path)?.read()?;
if let Some(base) = std::path::Path::new(&path).parent() {
let infos = H7CAD::io::xref::resolve_xrefs(&mut doc, base);
for i in &infos {
println!("XREF: {} -> {:?}", i.name, i.status);
}
}
println!("total entities: {}", doc.entities().count());
let inserts: Vec<_> = doc
.entities()
.filter_map(|e| if let EntityType::Insert(i) = e { Some(i.clone()) } else { None })
.collect();
println!("total inserts: {}", inserts.len());
let mut by_block: std::collections::HashMap<String, usize> = std::collections::HashMap::new();
for i in &inserts {
*by_block.entry(i.block_name.clone()).or_insert(0) += 1;
}
let mut by_block: Vec<_> = by_block.into_iter().collect();
by_block.sort_by(|a, b| b.1.cmp(&a.1));
println!("\ninserts grouped by block_name:");
for (name, n) in &by_block {
let sub_count = inserts.iter().find(|i| &i.block_name == name)
.map(|i| i.explode_from_document(&doc).len())
.unwrap_or(0);
let nested = doc.block_records.get(name)
.map(|br| br.entity_handles.iter()
.filter(|h| matches!(doc.get_entity(**h), Some(EntityType::Insert(_))))
.count())
.unwrap_or(0);
println!(" {:>4} × {} (sub={}, nested-inserts={})", n, name, sub_count, nested);
}
Ok(())
}
+87
View File
@@ -0,0 +1,87 @@
// Times each open phase: parse / purge / derived caches.
// Run with: cargo run --release --example time_open -- <path-to-dwg>
use acadrust::entities::EntityType;
use std::env;
use std::path::Path;
use std::time::Instant;
use H7CAD::io::{load_file, purge_corrupt_entities};
use H7CAD::scene::{build_derived_caches, Scene};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let path = env::args().nth(1).ok_or("usage: time_open <file>")?;
let t0 = Instant::now();
let mut doc = load_file(Path::new(&path))?;
let parse_ms = t0.elapsed().as_millis();
let t1 = Instant::now();
let dropped = purge_corrupt_entities(&mut doc);
let purge_ms = t1.elapsed().as_millis();
let t2 = Instant::now();
let caches = build_derived_caches(&doc);
let caches_ms = t2.elapsed().as_millis();
let mut counts = std::collections::HashMap::<&'static str, usize>::new();
let mut total = 0usize;
for e in doc.entities() {
total += 1;
let tag: &'static str = match e {
EntityType::Line(_) => "Line",
EntityType::Arc(_) => "Arc",
EntityType::Circle(_) => "Circle",
EntityType::LwPolyline(_) => "LwPolyline",
EntityType::Polyline2D(_) => "Polyline2D",
EntityType::Polyline3D(_) => "Polyline3D",
EntityType::Polyline(_) => "Polyline",
EntityType::Hatch(_) => "Hatch",
EntityType::Solid(_) => "Solid",
EntityType::RasterImage(_) => "RasterImage",
EntityType::Solid3D(_) => "Solid3D",
EntityType::Region(_) => "Region",
EntityType::Body(_) => "Body",
EntityType::Text(_) => "Text",
EntityType::MText(_) => "MText",
EntityType::Insert(_) => "Insert",
EntityType::Dimension(_) => "Dimension",
EntityType::Spline(_) => "Spline",
EntityType::Ellipse(_) => "Ellipse",
_ => "_other",
};
*counts.entry(tag).or_insert(0) += 1;
}
let mut counts: Vec<_> = counts.into_iter().collect();
counts.sort_by(|a, b| b.1.cmp(&a.1));
// Set up a Scene as the UI thread does and time first wire tessellation.
let mut scene = Scene::new();
scene.document = doc;
scene.world_offset = caches.world_offset;
scene.local_extent_max = caches.local_extent_max;
scene.hatches = caches.hatches.clone();
scene.images = caches.images.clone();
scene.meshes = caches.meshes.clone();
scene.bump_geometry();
scene.current_layout = "Model".to_string();
H7CAD::linetypes::populate_document(&mut scene.document);
let t3 = Instant::now();
let wires = scene.entity_wires();
let wires_ms = t3.elapsed().as_millis();
println!("file: {}", path);
println!("parse: {} ms", parse_ms);
println!("purge: {} ms (dropped {})", purge_ms, dropped);
println!("derived caches: {} ms", caches_ms);
println!("first wires: {} ms ({} wires)", wires_ms, wires.len());
println!(" hatches: {}", caches.hatches.len());
println!(" images: {}", caches.images.len());
println!(" meshes: {}", caches.meshes.len());
println!();
println!("entities: {}", total);
for (tag, n) in counts.iter().take(20) {
println!(" {:>14} {}", tag, n);
}
Ok(())
}
+10
View File
@@ -0,0 +1,10 @@
pub mod app;
pub mod command;
pub mod entities;
pub mod io;
pub mod linetypes;
pub mod modules;
pub mod patterns;
pub mod scene;
pub mod snap;
pub mod ui;