cloud_sdk/action_polling/
progress.rs1#[derive(Clone, Copy, Debug, Eq, PartialEq)]
3pub enum ProgressObservation {
4 Unavailable,
6 Percent(u8),
8 Reset(u8),
10}
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum ProgressPolicy {
15 Nondecreasing,
17 ExplicitResets {
19 max_resets: u16,
21 },
22 Unordered,
24}
25
26#[derive(Clone, Copy, Debug, Eq, PartialEq)]
28pub enum ProgressChange {
29 Unavailable,
31 Initial,
33 Unchanged,
35 Advanced,
37 Reset,
39 Unordered,
41}
42
43#[derive(Clone, Copy, Debug, Eq, PartialEq)]
44pub(crate) enum ProgressError {
45 Invalid,
46 Regressed,
47 ResetForbidden,
48 ResetLimit,
49}
50
51pub(crate) struct ProgressTracker {
52 policy: ProgressPolicy,
53 last: Option<u8>,
54 resets: u16,
55}
56
57impl ProgressTracker {
58 pub(crate) const fn new(policy: ProgressPolicy) -> Self {
59 Self {
60 policy,
61 last: None,
62 resets: 0,
63 }
64 }
65
66 pub(crate) fn observe(
67 &mut self,
68 observation: ProgressObservation,
69 ) -> Result<ProgressChange, ProgressError> {
70 let (value, explicit_reset) = match observation {
71 ProgressObservation::Unavailable => return Ok(ProgressChange::Unavailable),
72 ProgressObservation::Percent(value) => (value, false),
73 ProgressObservation::Reset(value) => (value, true),
74 };
75 if value > 100 {
76 return Err(ProgressError::Invalid);
77 }
78 if self.policy == ProgressPolicy::Unordered {
79 self.last = Some(value);
80 return Ok(ProgressChange::Unordered);
81 }
82 if explicit_reset {
83 let ProgressPolicy::ExplicitResets { max_resets } = self.policy else {
84 return Err(ProgressError::ResetForbidden);
85 };
86 let resets = self
87 .resets
88 .checked_add(1)
89 .ok_or(ProgressError::ResetLimit)?;
90 if resets > max_resets {
91 return Err(ProgressError::ResetLimit);
92 }
93 self.resets = resets;
94 self.last = Some(value);
95 return Ok(ProgressChange::Reset);
96 }
97 let change = match self.last {
98 None => ProgressChange::Initial,
99 Some(last) if value < last => return Err(ProgressError::Regressed),
100 Some(last) if value == last => ProgressChange::Unchanged,
101 Some(_) => ProgressChange::Advanced,
102 };
103 self.last = Some(value);
104 Ok(change)
105 }
106}