+enum ScaleSize {
+ Auto,
+ Times(f32),
+ Fixed(usize, usize)
+}
+
+impl FromStr for ScaleSize {
+ type Err = ();
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ if matches!(s, "" | "auto") {
+ Ok(ScaleSize::Auto)
+ } else if s.ends_with('x') || s.ends_with('X') {
+ let factor = s[..s.len() - 1].parse::<f32>().map_err(|_| ())?;
+ if factor > 0.0 {
+ Ok(ScaleSize::Times(factor))
+ } else {
+ Err(())
+ }
+ } else if s.contains('x') | s.contains('X') {
+ let mut dims = if s.contains('x') { s.split('x') } else { s.split('X') };
+ let w = dims.next().unwrap();
+ let h = dims.next().unwrap();
+ let width = w.parse::<usize>().map_err(|_| ())?;
+ let height = h.parse::<usize>().map_err(|_| ())?;
+ if width > 0 && height > 0 {
+ Ok(ScaleSize::Fixed(width, height))
+ } else {
+ Err(())
+ }
+ } else {
+ Err(())
+ }
+ }
+}
+