ferroui_base/animation/
iteration_count.rs1use crate::utilities::FormatError;
2use std::fmt;
3use std::hash::{Hash, Hasher};
4use std::str::FromStr;
5
6#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
8#[repr(i32)]
9pub enum IterationType {
10 #[default]
11 Many = 0,
12 Infinite = 1,
13}
14
15#[derive(Clone, Copy, Debug, Default)]
18pub struct IterationCount {
19 type_: IterationType,
20 value: u64,
21}
22
23impl IterationCount {
24 pub const INFINITE: IterationCount = IterationCount { type_: IterationType::Infinite, value: 0 };
26
27 pub const fn new(value: u64) -> Self {
29 Self { type_: IterationType::Many, value }
30 }
31
32 pub const fn with_type(value: u64, type_: IterationType) -> Self {
34 Self { type_, value }
35 }
36
37 pub const fn repeat_type(&self) -> IterationType {
39 self.type_
40 }
41
42 pub const fn is_infinite(&self) -> bool {
44 matches!(self.type_, IterationType::Infinite)
45 }
46
47 pub const fn value(&self) -> u64 {
49 self.value
50 }
51
52 pub fn parse(s: &str) -> Result<IterationCount, FormatError> {
54 let s = s.to_uppercase();
55 let s = s.trim();
56
57 if s.ends_with("INFINITE") {
58 Ok(Self::INFINITE)
59 } else {
60 if s.starts_with('-') {
61 return Err(FormatError::from_string("IterationCount can't be a negative number.".to_string()));
62 }
63
64 let digits = s.strip_prefix('+').unwrap_or(s);
65 if digits.is_empty() || !digits.bytes().all(|b| b.is_ascii_digit()) {
66 return Err(FormatError::from_string(format!("Invalid IterationCount string: \"{s}\".")));
67 }
68 let value = digits
69 .parse::<u64>()
70 .map_err(|_| FormatError::from_string(format!("Invalid IterationCount string: \"{s}\".")))?;
71
72 Ok(IterationCount::new(value))
73 }
74 }
75}
76
77impl PartialEq for IterationCount {
78 fn eq(&self, other: &Self) -> bool {
79 (self.is_infinite() && other.is_infinite()) || (self.value == other.value && self.type_ == other.type_)
80 }
81}
82
83impl Eq for IterationCount {}
84
85impl Hash for IterationCount {
86 fn hash<H: Hasher>(&self, state: &mut H) {
87 if self.is_infinite() {
89 IterationType::Infinite.hash(state);
90 } else {
91 self.value.hash(state);
92 self.type_.hash(state);
93 }
94 }
95}
96
97impl fmt::Display for IterationCount {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 if self.is_infinite() {
100 f.write_str("Infinite")
101 } else {
102 write!(f, "{}", self.value)
103 }
104 }
105}
106
107impl FromStr for IterationCount {
108 type Err = FormatError;
109 fn from_str(s: &str) -> Result<Self, Self::Err> {
110 IterationCount::parse(s)
111 }
112}