summaryrefslogtreecommitdiff
path: root/src/values/rotation.rs
diff options
context:
space:
mode:
authorPolesznyák Márk László <116908301+pml68@users.noreply.github.com>2025-03-23 02:49:57 +0100
committerGitHub <noreply@github.com>2025-03-23 02:49:57 +0100
commit3076889c00116b22f022792471253e7188c6e93e (patch)
treebff0cda7a9152e9f94d3176bbf5acaf879394f5f /src/values/rotation.rs
parentfeat: update to Rust 2024 (diff)
parentfeat: finish `ApplyOptions` impls (diff)
downloadiced-builder-3076889c00116b22f022792471253e7188c6e93e.tar.gz
Merge pull request #7 from pml68/feat/options-backend
Options backend done (for now)
Diffstat (limited to '')
-rwxr-xr-xsrc/values/rotation.rs114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/values/rotation.rs b/src/values/rotation.rs
new file mode 100755
index 0000000..90e3f84
--- /dev/null
+++ b/src/values/rotation.rs
@@ -0,0 +1,114 @@
+use std::num::ParseFloatError;
+use std::str::FromStr;
+
+use iced::{Radians, Rotation};
+
+use super::Value;
+
+#[derive(Debug, thiserror::Error, Clone, PartialEq)]
+pub enum ParseRotationError {
+ #[error("float parsing error: {0}")]
+ ParseFloatError(ParseFloatError),
+ #[error("invalid prefix")]
+ InvalidPrefix,
+ #[error("cannot parse rotation from empty string")]
+ Empty,
+}
+
+impl From<ParseFloatError> for ParseRotationError {
+ fn from(value: ParseFloatError) -> Self {
+ Self::ParseFloatError(value)
+ }
+}
+
+impl Value for Rotation {
+ type Err = ParseRotationError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let s = s.trim();
+
+ if s.is_empty() {
+ return Err(ParseRotationError::Empty);
+ }
+
+ if s.starts_with(|c: char| !c.is_ascii_digit()) {
+ let (prefix, value) = s.split_at(1);
+ match prefix.to_lowercase().as_str() {
+ "s" => Ok(Rotation::Solid(Radians(f32::from_str(value)?))),
+ "f" => Ok(Rotation::Floating(Radians(f32::from_str(value)?))),
+ _ => Err(ParseRotationError::InvalidPrefix),
+ }
+ } else {
+ Ok(Rotation::Floating(Radians(f32::from_str(s)?)))
+ }
+ }
+
+ fn to_string(&self) -> String {
+ match self {
+ Self::Floating(value) => format!("f{}", value),
+ Self::Solid(value) => format!("s{}", value),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn can_parse_without_prefix() {
+ assert_eq!(
+ Rotation::from_str("10.5"),
+ Ok(Rotation::Floating(Radians(10.5)))
+ )
+ }
+
+ #[test]
+ fn can_parse_with_s_prefix() {
+ assert_eq!(
+ Rotation::from_str(" s12.3"),
+ Ok(Rotation::Solid(Radians(12.3)))
+ );
+
+ assert_eq!(
+ Rotation::from_str("S9.4"),
+ Ok(Rotation::Solid(Radians(9.4)))
+ )
+ }
+
+ #[test]
+ fn can_parse_with_f_prefix() {
+ assert_eq!(
+ Rotation::from_str("f16.9"),
+ Ok(Rotation::Floating(Radians(16.9)))
+ );
+
+ assert_eq!(
+ Rotation::from_str("F21.45 "),
+ Ok(Rotation::Floating(Radians(21.45)))
+ )
+ }
+
+ #[test]
+ fn cant_parse_invalid_prefix() {
+ assert_eq!(
+ Rotation::from_str("a6.0"),
+ Err(ParseRotationError::InvalidPrefix)
+ )
+ }
+
+ #[test]
+ fn cant_parse_invalid_float() {
+ assert_eq!(
+ Rotation::from_str("3.a"),
+ Err(ParseRotationError::ParseFloatError(
+ f32::from_str("3.a").expect_err("float parse should fail")
+ ))
+ )
+ }
+
+ #[test]
+ fn cant_parse_empty_string() {
+ assert_eq!(Rotation::from_str(" "), Err(ParseRotationError::Empty))
+ }
+}