sem_reg/
data_conversion.rs

1pub(crate) mod byte_seq;
2pub(crate) mod format;
3pub mod hex_bytes;
4pub(crate) mod time;
5
6pub use byte_seq::ParseError;
7
8use std::ops::Deref;
9
10#[derive(Debug)]
11pub struct TrackedValue<T: PartialEq> {
12    old: T,
13    new: Option<T>,
14}
15
16impl<T: PartialEq> TrackedValue<T> {
17    pub fn new(value: T) -> Self {
18        Self {
19            old: value,
20            new: None,
21        }
22    }
23
24    pub fn set(&mut self, value: T) {
25        self.new = Some(value);
26    }
27
28    pub fn reset(&mut self) {
29        self.new = None;
30    }
31
32    pub fn changed(&self) -> bool {
33        if let Some(new) = &self.new {
34            *new != self.old
35        } else {
36            false
37        }
38    }
39}
40
41impl<T: PartialEq> Deref for TrackedValue<T> {
42    type Target = T;
43
44    fn deref(&self) -> &Self::Target {
45        self.new.as_ref().unwrap_or(&self.old)
46    }
47}
48
49impl<T: PartialEq> PartialEq for TrackedValue<T> {
50    fn eq(&self, other: &Self) -> bool {
51        self.new
52            .as_ref()
53            .unwrap_or(&self.old)
54            .eq(other.new.as_ref().unwrap_or(&other.old))
55    }
56}
57
58/// The mode of operation when parsing and checking values for validity.
59#[derive(Clone, Copy, PartialEq, Debug)]
60pub enum Strictness {
61    /// Only accept known formats exact to the byte, and only value ranges last known to be valid. Should normally be used.
62    Strict,
63    /// Turn a blind eye regarding certain aspects when parsing or checking values for validity. Can be tried when strict mode doesn't work, or when you must overcome certain limitations. Doesn't influence serialization. Rather than this being used regularly, the parsing or other code should be updated.
64    Lenient,
65}
66
67impl Strictness {
68    pub fn from_lenient_bool(lenient: bool) -> Self {
69        if lenient {
70            Self::Lenient
71        } else {
72            Self::Strict
73        }
74    }
75
76    pub fn is_strict(&self) -> bool {
77        *self == Strictness::Strict
78    }
79
80    pub fn is_lenient(&self) -> bool {
81        *self == Strictness::Lenient
82    }
83}
84
85pub trait ResultOrElseIf<T, E> {
86    fn or_else_if<O>(self, flag: bool, op: O) -> Result<T, E>
87    where
88        O: FnOnce(E) -> Result<T, E>;
89}
90
91impl<T, E> ResultOrElseIf<T, E> for Result<T, E> {
92    fn or_else_if<O>(self, flag: bool, op: O) -> Result<T, E>
93    where
94        O: FnOnce(E) -> Result<T, E>,
95    {
96        match self {
97            Ok(t) => Ok(t),
98            Err(e) => {
99                if flag {
100                    op(e)
101                } else {
102                    Err(e)
103                }
104            }
105        }
106    }
107}