address review: count exploded array objects before cloning; scan each block's constants once

This commit is contained in:
Dylan M. Taylor
2026-11-10 22:57:57 +00:00
parent a363185aa6
commit c979db0807
2 changed files with 21 additions and 6 deletions
+13 -4
View File
@@ -193,7 +193,19 @@ pub(crate) fn explode_array(d: &Drawing, e: &Entity) -> Option<Vec<Entity>> {
let p = d.array_params(e)?;
let blk = d.block(&ins.block)?;
let m = ins.transform(blk.base.xy());
let mut out = Vec::new();
// Count first: a hostile array must be refused before any entity is cloned.
let total = blk
.entities
.iter()
.map(|it| match &it.kind {
EntityKind::Insert(i) if i.block.eq_ignore_ascii_case(&p.source) => d.block(&i.block).map_or(1, |b| b.entities.len()),
_ => 1,
})
.fold(0usize, usize::saturating_add);
if total > MAX_EXPLODED_OBJECTS {
return None;
}
let mut out = Vec::with_capacity(total);
for item in blk.entities.iter() {
let item = placed(e, item, &m);
let source = match &item.kind {
@@ -202,9 +214,6 @@ pub(crate) fn explode_array(d: &Drawing, e: &Entity) -> Option<Vec<Entity>> {
};
match source {
Some((im, b)) => {
if out.len().saturating_add(b.entities.len()) > MAX_EXPLODED_OBJECTS {
return None;
}
out.extend(b.entities.iter().map(|se| placed(&item, se, &im)));
}
None => out.push(item),
+8 -2
View File
@@ -131,6 +131,7 @@ fn selected_tags(ents: &[std::sync::Arc<cadcraft_doc::Entity>], d: &Drawing, o:
selected.push(tag);
}
};
let mut scanned = std::collections::HashSet::new();
for entity in ents {
let EntityKind::Insert(ins) = &entity.kind else { continue };
let anonymous = ins.block.starts_with('*') || d.block(&ins.block).is_some_and(|b| b.anonymous);
@@ -140,9 +141,14 @@ fn selected_tags(ents: &[std::sync::Arc<cadcraft_doc::Entity>], d: &Drawing, o:
for attribute in &ins.attribs {
add(&attribute.tag);
}
if let Some(block) = d.block(&ins.block) {
// A block's constants are read once, however many inserts reference it.
if scanned.insert(ins.block.as_str())
&& let Some(block) = d.block(&ins.block)
{
for entity in block.entities.iter() {
if let EntityKind::AttDef(attribute) = &entity.kind && attribute.constant {
if let EntityKind::AttDef(attribute) = &entity.kind
&& attribute.constant
{
add(&attribute.tag);
}
}