leetcode_tui_core/
step.rs1use 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}