mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-24 10:10:05 -06:00
Refuse numbers separated by spaces or a unit in number fields
Found while testing crates/ui-egui/src/calc.rs:34-41 (eval) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
09aaf9bf15
commit
fb5b2dc40a
+27
-14
@@ -15,25 +15,27 @@ pub fn eval(text: &str, current: f64) -> Option<f64> {
|
||||
if raw.len() > MAX_LEN {
|
||||
return None;
|
||||
}
|
||||
// letters between two digits (`1e3`, `10x20`) are not a unit: refuse rather than guess
|
||||
let mut i = 0;
|
||||
while let Some(c) = raw.get(i) {
|
||||
if c.is_alphabetic() {
|
||||
let end = raw.iter().skip(i).position(|c| !c.is_alphabetic()).map_or(raw.len(), |n| i + n);
|
||||
let before = i.checked_sub(1).and_then(|b| raw.get(b)).is_some_and(|c| c.is_ascii_digit());
|
||||
let after = raw.get(end).is_some_and(|c| c.is_ascii_digit() || *c == '.');
|
||||
if before && after {
|
||||
return None;
|
||||
}
|
||||
i = end;
|
||||
} else {
|
||||
i += 1;
|
||||
// spaces or a unit between two numbers (`1e3`, `10x20`, `10 x 20`, `1920 1080`) would fuse them
|
||||
// into one number once dropped: refuse rather than guess
|
||||
let skipped = |c: &char| c.is_alphabetic() || c.is_whitespace() || matches!(c, '%' | '°');
|
||||
let mut after_number = false;
|
||||
let mut gap = false;
|
||||
for c in &raw {
|
||||
if skipped(c) {
|
||||
gap = true;
|
||||
continue;
|
||||
}
|
||||
let number_char = c.is_ascii_digit() || *c == '.';
|
||||
if number_char && after_number && gap {
|
||||
return None;
|
||||
}
|
||||
after_number = number_char;
|
||||
gap = false;
|
||||
}
|
||||
let chars: Vec<char> = raw
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|c| !(c.is_alphabetic() || c.is_whitespace() || matches!(c, '%' | '°')))
|
||||
.filter(|c| !skipped(c))
|
||||
.map(|c| match c {
|
||||
'×' => '*',
|
||||
'÷' => '/',
|
||||
@@ -181,4 +183,15 @@ mod tests {
|
||||
assert_eq!(eval("1e3", 0.0), None);
|
||||
assert_eq!(eval("10x20", 0.0), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numbers_separated_by_spaces_or_a_unit_are_not_merged() {
|
||||
for bad in ["10 x 20", "1 e 3", "1920 1080", "10px 20", "50% 2", "1 .5"] {
|
||||
assert_eq!(eval(bad, 0.0), None, "{bad:?}");
|
||||
}
|
||||
assert_eq!(eval("100 * 2", 0.0), Some(200.0));
|
||||
assert_eq!(eval("10px", 0.0), Some(10.0));
|
||||
assert_eq!(eval("10 px * 2", 0.0), Some(20.0));
|
||||
assert_eq!(eval("*2", 5.0), Some(10.0));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user