leetcode_tui_core/
step.rs

1use std::{num::ParseIntError, str::FromStr};
2
3pub enum Step {
4    Fixed(isize),
5    Percent(i8),
6}
7
8impl Default for Step {
9    fn default() -> Self {
10        Self::Fixed(0)
11    }
12}
13
14impl FromStr for Step {
15    type Err = ParseIntError;
16
17    fn from_str(s: &str) -> Result<Self, Self::Err> {
18        Ok(if let Some(s) = s.strip_suffix('%') {
19            Self::Percent(s.parse()?)
20        } else {
21            Self::Fixed(s.parse()?)
22        })
23    }
24}
25
26impl From<isize> for Step {
27    fn from(n: isize) -> Self {
28        Self::Fixed(n)
29    }
30}
31
32impl From<usize> for Step {
33    fn from(n: usize) -> Self {
34        Self::Fixed(n as isize)
35    }
36}
37
38impl Step {
39    #[inline]
40    fn fixed<F: FnOnce() -> usize>(self, f: F) -> isize {
41        match self {
42            Self::Fixed(n) => n,
43            Self::Percent(0) => 0,
44            Self::Percent(n) => n as isize * f() as isize / 100,
45        }
46    }
47
48    #[inline]
49    pub fn add<F: FnOnce() -> usize>(self, pos: usize, f: F) -> usize {
50        let fixed = self.fixed(f);
51        if fixed > 0 {
52            pos + fixed as usize
53        } else {
54            pos.saturating_sub(fixed.unsigned_abs())
55        }
56    }
57
58    #[inline]
59    pub fn is_positive(&self) -> bool {
60        match *self {
61            Self::Fixed(n) => n > 0,
62            Self::Percent(n) => n > 0,
63        }
64    }
65}