From e67680b0030a890d75ed35bc1144d1e8880dd3be Mon Sep 17 00:00:00 2001 From: Polesznyák Márk Date: Sat, 15 Nov 2025 12:33:22 +0100 Subject: feat: add `Grid` as a usable widget --- src/values/sizing.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/values/sizing.rs (limited to 'src/values/sizing.rs') diff --git a/src/values/sizing.rs b/src/values/sizing.rs new file mode 100644 index 0000000..e6a5086 --- /dev/null +++ b/src/values/sizing.rs @@ -0,0 +1,109 @@ +use std::num::ParseFloatError; +use std::str::FromStr; + +use iced::Length; +use iced::widget::grid::Sizing; + +use super::Value; +use super::length::ParseLengthError; + +#[derive(Debug, thiserror::Error, Clone, PartialEq)] +pub enum ParseSizingError { + #[error("float parsing error: {0}")] + ParseFloatError(ParseFloatError), + #[error("length parsing error: {0}")] + ParseLengthError(#[from] ParseLengthError), + #[error("invalid prefix")] + InvalidPrefix, + #[error("missing prefix")] + MissingPrefix, + #[error("cannot parse sizing from empty string")] + Empty, +} + +impl From for ParseSizingError { + fn from(value: ParseFloatError) -> Self { + Self::ParseFloatError(value) + } +} + +impl Value for Sizing { + type Err = ParseSizingError; + + fn from_str(s: &str) -> Result { + let s = s.trim(); + + if s.is_empty() { + return Err(ParseSizingError::Empty); + } + + if s.starts_with(|c: char| c.is_ascii_digit()) { + return Err(ParseSizingError::MissingPrefix); + } + + let (prefix, value) = s.split_at(2); + match prefix.to_lowercase().as_str() { + "ar" => Ok(Self::AspectRatio(f32::from_str(value)?)), + "ed" => Ok(Self::EvenlyDistribute(Length::from_str(value)?)), + _ => Err(ParseSizingError::InvalidPrefix), + } + } + + fn to_string(&self) -> String { + match self { + Self::AspectRatio(ratio) => format!("ar{ratio}"), + Self::EvenlyDistribute(length) => { + format!("ed{}", length.to_string()) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_parse_ratio() { + assert_eq!(Sizing::from_str("ar5.1"), Ok(Sizing::AspectRatio(5.1))) + } + + #[test] + fn can_parse_distribute_with_space() { + assert_eq!( + Sizing::from_str(" edfp2 "), + Ok(Sizing::EvenlyDistribute(Length::FillPortion(2))) + ) + } + + #[test] + fn cant_parse_invalid_prefix() { + assert_eq!( + Sizing::from_str("bc4.1 "), + Err(ParseSizingError::InvalidPrefix) + ) + } + + #[test] + fn cant_parse_invalid_float() { + assert_eq!( + Sizing::from_str(" ar2.a"), + Err(ParseSizingError::ParseFloatError( + f32::from_str("2.a").expect_err("float parse should fail") + )) + ) + } + + #[test] + fn cant_parse_with_missing_prefix() { + assert_eq!( + Sizing::from_str("2.4"), + Err(ParseSizingError::MissingPrefix) + ) + } + + #[test] + fn cant_parse_empty_string() { + assert_eq!(Sizing::from_str(" "), Err(ParseSizingError::Empty)) + } +} -- cgit v1.2.3