Configurations: a design keeps up to 2048 rules (#6221)

* Test: a design keeps several hundred configuration rules

An assembly that switches a few hundred parts on and off, by two rules each, needs hundreds of
rules; the saved-rule budget refused more than 128.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PsiqyXWBFGTCX9J51bhysc

* Configurations: a design keeps up to 2048 rules

Problem: a configuration table kept at most 128 rules. A rule drives one feature's suppression,
so an assembly that switches a few hundred parts on and off (by two rules each) could not keep
its rules. Copying rules for an independent component copy looked up each new id by scanning all
rules, which a larger table makes slow.

Solution: MAX_RULES is 2048; a copy looks its new ids up in a set of the ids taken. The docs say
the new limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PsiqyXWBFGTCX9J51bhysc

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
NOWN-DEV
2026-10-25 02:29:25 +00:00
committed by GitHub
parent 3592031d5e
commit 24ed21998b
3 changed files with 21 additions and 6 deletions
+6 -2
View File
@@ -1,7 +1,7 @@
//! Configuration graph remapping for independent component copies.
use super::{Column, ConfigTable};
use crate::{DocError, Result};
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
#[derive(Clone, Debug, Default)]
pub struct ConfigCloneMaps {
@@ -102,6 +102,9 @@ impl ConfigTable {
}
}
}
// The ids taken so far, looked up rather than scanned: copies of rules whose ids share
// their first 40 characters try one id after another.
let mut taken: BTreeSet<String> = next.rules.iter().map(|rule| rule.id.clone()).collect();
for rule in &self.rules {
if let Some(mut copied) = rule.clone_for_targets(maps) {
if next.rules.len() >= super::MAX_RULES {
@@ -110,8 +113,9 @@ impl ConfigTable {
let stem: String = rule.id.chars().take(40).collect();
copied.id = (1..=super::MAX_RULES + 1)
.map(|i| format!("{stem}_copy{i}"))
.find(|id| !next.rules.iter().any(|rule| rule.id == *id))
.find(|id| !taken.contains(id))
.ok_or_else(|| DocError::Invalid("no configuration rule ID available".into()))?;
taken.insert(copied.id.clone());
copied.name = format!("{} (copy)", rule.name.chars().take(120).collect::<String>());
next.rules.push(copied);
}
+14 -3
View File
@@ -6,7 +6,9 @@ use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::{BTreeMap, BTreeSet};
pub const MAX_RULES: usize = 128;
/// Most configuration rules a design keeps. A rule drives one feature's suppression, so an
/// assembly that switches a few hundred parts on and off, by two rules each, needs hundreds.
pub const MAX_RULES: usize = 2048;
const MAX_NODES: usize = 64;
const MAX_DEPTH: usize = 8;
@@ -626,7 +628,16 @@ mod tests {
.unwrap();
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":[valid.clone()]}})).is_ok());
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":null}})).is_err());
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":vec![valid.clone();129]}})).is_err());
// An assembly that switches a few hundred parts on and off, by two rules each, keeps them.
let many: Vec<Value> = (0..600)
.map(|i| {
let mut r = valid.clone();
r["id"] = serde_json::json!(format!("r{i}"));
r
})
.collect();
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":many}})).is_ok());
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":vec![valid.clone();MAX_RULES + 1]}})).is_err());
let mut condition = serde_json::json!({"type":"always"});
for _ in 0..8 {
condition = serde_json::json!({"type":"not","condition":condition});
@@ -690,7 +701,7 @@ mod tests {
Value::Null,
serde_json::json!([deep]),
serde_json::json!([wide]),
serde_json::json!(vec![valid; 129]),
serde_json::json!(vec![valid; MAX_RULES + 1]),
serde_json::json!([invalid_context]),
] {
let mut saved = serde_json::to_value(design()).unwrap();
+1 -1
View File
@@ -147,7 +147,7 @@ or restrictions leave the previous document intact and explain the failure. Dele
before removing the last row. Parameter renames update rule targets and expressions; rule
references prevent parameter deletion until removed.
Tables support at most 128 rules; conditions allow eight levels and 64 nodes, and allowed
Tables support at most 2048 rules; conditions allow eight levels and 64 nodes, and allowed
value lists support up to 128 expressions. These bounds are checked before saved rules are
decoded. Driven appearance/material rules and repeated fixed-point evaluation are outside
the current rule scope.