Allow for floating point numbers in durations (fixes #447)

This commit is contained in:
elkowar 2022-04-29 14:20:12 +02:00
parent 34d929f097
commit d1b222fa7f
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
10 changed files with 99 additions and 22 deletions

View file

@ -169,17 +169,18 @@ impl DynVal {
s.trim_end_matches("ms").parse().map_err(|e| ConversionError::new(self.clone(), "integer", e))?, s.trim_end_matches("ms").parse().map_err(|e| ConversionError::new(self.clone(), "integer", e))?,
)) ))
} else if s.ends_with('s') { } else if s.ends_with('s') {
Ok(Duration::from_secs( let secs = s.trim_end_matches('s').parse::<f64>().map_err(|e| ConversionError::new(self.clone(), "number", e))?;
s.trim_end_matches('s').parse().map_err(|e| ConversionError::new(self.clone(), "integer", e))?, Ok(Duration::from_millis(f64::floor(secs * 1000f64) as u64))
)) } else if s.ends_with('m') || s.ends_with("min") {
} else if s.ends_with('m') { let minutes = s
Ok(Duration::from_secs( .trim_end_matches("min")
s.trim_end_matches('m').parse::<u64>().map_err(|e| ConversionError::new(self.clone(), "integer", e))? * 60, .trim_end_matches('m')
)) .parse::<f64>()
.map_err(|e| ConversionError::new(self.clone(), "number", e))?;
Ok(Duration::from_secs(f64::floor(minutes * 60f64) as u64))
} else if s.ends_with('h') { } else if s.ends_with('h') {
Ok(Duration::from_secs( let hours = s.trim_end_matches('h').parse::<f64>().map_err(|e| ConversionError::new(self.clone(), "number", e))?;
s.trim_end_matches('h').parse::<u64>().map_err(|e| ConversionError::new(self.clone(), "integer", e))? * 60 * 60, Ok(Duration::from_secs(f64::floor(hours * 60f64 * 60f64) as u64))
))
} else { } else {
Err(ConversionError { value: self.clone(), target_type: "duration", source: None }) Err(ConversionError { value: self.clone(), target_type: "duration", source: None })
} }
@ -238,13 +239,25 @@ mod test {
use super::*; use super::*;
#[test] #[test]
fn test_parse_vec() { fn test_parse_vec() {
insta::assert_debug_snapshot!(DynVal::from_string("[]".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("[]").as_vec());
insta::assert_debug_snapshot!(DynVal::from_string("[hi]".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("[hi]").as_vec());
insta::assert_debug_snapshot!(DynVal::from_string("[hi,ho,hu]".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("[hi,ho,hu]").as_vec());
insta::assert_debug_snapshot!(DynVal::from_string("[hi\\,ho]".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("[hi\\,ho]").as_vec());
insta::assert_debug_snapshot!(DynVal::from_string("[hi\\,ho,hu]".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("[hi\\,ho,hu]").as_vec());
insta::assert_debug_snapshot!(DynVal::from_string("".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("").as_vec());
insta::assert_debug_snapshot!(DynVal::from_string("[a,b".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("[a,b").as_vec());
insta::assert_debug_snapshot!(DynVal::from_string("a]".to_string()).as_vec()); insta::assert_debug_snapshot!(DynVal::from("a]").as_vec());
}
#[test]
fn test_parse_duration() {
insta::assert_debug_snapshot!(DynVal::from("100ms").as_duration());
insta::assert_debug_snapshot!(DynVal::from("1s").as_duration());
insta::assert_debug_snapshot!(DynVal::from("0.1s").as_duration());
insta::assert_debug_snapshot!(DynVal::from("5m").as_duration());
insta::assert_debug_snapshot!(DynVal::from("5min").as_duration());
insta::assert_debug_snapshot!(DynVal::from("0.5m").as_duration());
insta::assert_debug_snapshot!(DynVal::from("1h").as_duration());
insta::assert_debug_snapshot!(DynVal::from("0.5h").as_duration());
} }
} }

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"1s\").as_duration()"
---
Ok(
1s,
)

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"0.1s\").as_duration()"
---
Ok(
100ms,
)

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"5m\").as_duration()"
---
Ok(
300s,
)

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"5min\").as_duration()"
---
Ok(
300s,
)

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"0.5m\").as_duration()"
---
Ok(
30s,
)

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"1h\").as_duration()"
---
Ok(
3600s,
)

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"0.5h\").as_duration()"
---
Ok(
1800s,
)

View file

@ -0,0 +1,8 @@
---
source: crates/simplexpr/src/dynval.rs
expression: "DynVal::from(\"100ms\").as_duration()"
---
Ok(
100ms,
)

View file

@ -19,7 +19,7 @@ Config(
span: Span(29, 33, 0), span: Span(29, 33, 0),
), ),
], ],
widget: WidgetUse( widget: Basic(BasicWidgetUse(
name: "foo", name: "foo",
attrs: Attributes( attrs: Attributes(
span: Span(51, 61, 0), span: Span(51, 61, 0),
@ -33,7 +33,7 @@ Config(
children: [], children: [],
span: Span(47, 62, 0), span: Span(47, 62, 0),
name_span: Span(48, 51, 0), name_span: Span(48, 51, 0),
), )),
span: Span(9, 63, 0), span: Span(9, 63, 0),
args_span: Span(24, 34, 0), args_span: Span(24, 34, 0),
), ),
@ -57,7 +57,7 @@ Config(
)), )),
stacking: Foreground, stacking: Foreground,
monitor_number: Some(12), monitor_number: Some(12),
widget: WidgetUse( widget: Basic(BasicWidgetUse(
name: "bar", name: "bar",
attrs: Attributes( attrs: Attributes(
span: Span(467, 478, 0), span: Span(467, 478, 0),
@ -71,7 +71,7 @@ Config(
children: [], children: [],
span: Span(463, 479, 0), span: Span(463, 479, 0),
name_span: Span(464, 467, 0), name_span: Span(464, 467, 0),
), )),
resizable: true, resizable: true,
backend_options: BackendWindowOptions( backend_options: BackendWindowOptions(
wm_ignore: false, wm_ignore: false,