mirror of
https://github.com/storytold/cadcraft.git
synced 2026-11-02 16:31:48 -06:00
Refuse invalid counts in JSON arraypolar and arrayrect (#2399)
Found while testing crates/engine/src/cmd/array.rs:332-334 (count_or, used by run_arrayrect at 338-340 and run_arraypolar at 363-365) Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
7efb32b455
commit
c2695f6ab0
@@ -328,16 +328,19 @@ fn run_array(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
(spec.run)(s, p)
|
||||
}
|
||||
|
||||
/// A count parameter (at least 1).
|
||||
fn count_or(p: &Value, key: &str, default: u64) -> u64 {
|
||||
p.get(key).and_then(Value::as_u64).unwrap_or(default).max(1)
|
||||
/// A count parameter (at least 1); a missing key gives the default, an invalid value is refused.
|
||||
fn count_or(cmd: &str, p: &Value, key: &str, default: u64) -> Result<u64> {
|
||||
match p.get(key) {
|
||||
None | Some(Value::Null) => Ok(default),
|
||||
Some(v) => v.as_u64().filter(|n| *n >= 1).ok_or_else(|| bad(cmd, format!("`{key}` must be a whole number of at least 1"))),
|
||||
}
|
||||
}
|
||||
|
||||
fn run_arrayrect(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let hs = targets(s, p)?;
|
||||
let rows = count_or(p, "rows", 3);
|
||||
let cols = count_or(p, "cols", 4);
|
||||
let levels = count_or(p, "levels", 1);
|
||||
let rows = count_or("arrayrect", p, "rows", 3)?;
|
||||
let cols = count_or("arrayrect", p, "cols", 4)?;
|
||||
let levels = count_or("arrayrect", p, "levels", 1)?;
|
||||
check_size(s, rows.saturating_mul(cols).saturating_mul(levels), hs.len())?;
|
||||
let kind = ArrayKind::Rect(RectArray {
|
||||
cols: count32(cols),
|
||||
@@ -360,9 +363,9 @@ fn run_arrayrect(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
fn run_arraypolar(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let hs = targets(s, p)?;
|
||||
let c = point_req("arraypolar", p, "center")?;
|
||||
let n = count_or(p, "count", 6);
|
||||
let rows = count_or(p, "rows", 1);
|
||||
let levels = count_or(p, "levels", 1);
|
||||
let n = count_or("arraypolar", p, "count", 6)?;
|
||||
let rows = count_or("arraypolar", p, "rows", 1)?;
|
||||
let levels = count_or("arraypolar", p, "levels", 1)?;
|
||||
check_size(s, n.saturating_mul(rows).saturating_mul(levels), hs.len())?;
|
||||
let base = point_param(p, "base").or_else(|| s.doc().ok().and_then(|d| first_center(d, &hs))).unwrap_or(c);
|
||||
let row_spacing = f64_or(p, "rowSpacing", 1.0);
|
||||
|
||||
@@ -1444,3 +1444,22 @@ fn hostile_variable_like_input_never_panics() {
|
||||
s.cmdline("pickadd").unwrap();
|
||||
assert!(setvar_prompt_open(&s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_counts_reject_invalid_values() {
|
||||
let mut s = Session::new();
|
||||
s.execute("line", &json!({"points": [[0, 0], [1, 0]]})).unwrap();
|
||||
for bad in [json!(-3), json!(0), json!(2.5)] {
|
||||
for key in ["count", "rows", "levels"] {
|
||||
let mut p = json!({"center": [0, 0], "associative": false});
|
||||
p[key] = bad.clone();
|
||||
assert!(s.execute("arraypolar", &p).is_err(), "arraypolar {key}={bad}");
|
||||
}
|
||||
for key in ["rows", "cols", "levels"] {
|
||||
let mut p = json!({"associative": false});
|
||||
p[key] = bad.clone();
|
||||
assert!(s.execute("arrayrect", &p).is_err(), "arrayrect {key}={bad}");
|
||||
}
|
||||
}
|
||||
s.execute("arraypolar", &json!({"center": [0, 0], "count": 1, "associative": false})).unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user