Skip to main content

fastlib/base/
value.rs

1use std::cmp::min;
2use std::fmt::{Display, Formatter, Write};
3
4use crate::base::decimal::Decimal;
5use crate::utils::bytes::{bytes_delta, bytes_tail, string_delta, string_tail, string_to_bytes};
6use crate::{Error, Result};
7
8/// Represents type of field instruction.
9///
10/// It can be field instruction (including sequence and group) or template reference instruction.
11#[derive(Debug, PartialEq, Clone)]
12pub enum ValueType {
13    UInt32,
14    Int32,
15    UInt64,
16    Int64,
17    Length,
18    Exponent,
19    Mantissa,
20    Decimal,
21    ASCIIString,
22    UnicodeString,
23    Bytes,
24    Sequence,
25    Group,
26    TemplateReference,
27}
28
29impl ValueType {
30    /// Creates new value type from tag.
31    /// # Errors
32    /// Returns error if tag is unknown.
33    pub fn new_from_tag(tag: &str, unicode: bool) -> Result<Self> {
34        match tag {
35            "uInt32" => Ok(Self::UInt32),
36            "int32" => Ok(Self::Int32),
37            "uInt64" => Ok(Self::UInt64),
38            "int64" => Ok(Self::Int64),
39            "length" => Ok(Self::Length),
40            "exponent" => Ok(Self::Exponent),
41            "mantissa" => Ok(Self::Mantissa),
42            "decimal" => Ok(Self::Decimal),
43            "string" => {
44                if unicode {
45                    Ok(Self::UnicodeString)
46                } else {
47                    Ok(Self::ASCIIString)
48                }
49            }
50            "byteVector" => Ok(Self::Bytes),
51            "sequence" => Ok(Self::Sequence),
52            "group" => Ok(Self::Group),
53            "templateRef" => Ok(Self::TemplateReference),
54            _ => Err(Error::Static(format!("Unknown type: {tag}"))),
55        }
56    }
57
58    #[must_use]
59    pub fn type_str(&self) -> &'static str {
60        match self {
61            ValueType::UInt32 => "uInt32",
62            ValueType::Int32 => "int32",
63            ValueType::UInt64 => "uInt64",
64            ValueType::Int64 => "int64",
65            ValueType::Length => "length",
66            ValueType::Exponent => "exponent",
67            ValueType::Mantissa => "mantissa",
68            ValueType::Decimal => "decimal",
69            ValueType::ASCIIString | ValueType::UnicodeString => "string",
70            ValueType::Bytes => "byteVector",
71            ValueType::Sequence => "sequence",
72            ValueType::Group => "group",
73            ValueType::TemplateReference => "templateRef",
74        }
75    }
76
77    /// Returns default value of the self type.
78    /// # Errors
79    /// Returns error if type does not have default type.
80    pub fn to_default_value(&self) -> Result<Value> {
81        match self {
82            ValueType::Int32 | ValueType::Exponent => Ok(Value::Int32(0)),
83            ValueType::Int64 | ValueType::Mantissa => Ok(Value::Int64(0)),
84            ValueType::UInt32 | ValueType::Length => Ok(Value::UInt32(0)),
85            ValueType::UInt64 => Ok(Value::UInt64(0)),
86            ValueType::Decimal => Ok(Value::Decimal(Decimal::default())),
87            ValueType::ASCIIString => Ok(Value::ASCIIString(String::new())),
88            ValueType::UnicodeString => Ok(Value::UnicodeString(String::new())),
89            ValueType::Bytes => Ok(Value::Bytes(Vec::new())),
90            _ => Err(Error::Runtime(format!(
91                "{} cannot be converted to value",
92                self.type_str()
93            ))),
94        }
95    }
96
97    /// Converts string to the self type.
98    /// # Errors
99    /// Returns error if type is not convertible from string.
100    pub fn str_to_value(&self, s: &str) -> Result<Value> {
101        let mut value = match self {
102            ValueType::Int32 | ValueType::Exponent => Value::Int32(0),
103            ValueType::Int64 | ValueType::Mantissa => Value::Int64(0),
104            ValueType::UInt32 | ValueType::Length => Value::UInt32(0),
105            ValueType::UInt64 => Value::UInt64(0),
106            ValueType::Decimal => Value::Decimal(Decimal::default()),
107            ValueType::ASCIIString => Value::ASCIIString(String::new()),
108            ValueType::UnicodeString => Value::UnicodeString(String::new()),
109            ValueType::Bytes => Value::Bytes(Vec::new()),
110            _ => {
111                return Err(Error::Runtime(format!(
112                    "{} cannot be converted to value",
113                    self.type_str()
114                )));
115            }
116        };
117        value.set_from_string(s)?;
118        Ok(value)
119    }
120
121    #[allow(clippy::match_like_matches_macro)]
122    #[must_use]
123    pub fn matches_type(&self, v: &Value) -> bool {
124        match (self, v) {
125            (ValueType::UInt32, Value::UInt32(_)) => true,
126            (ValueType::Int32, Value::Int32(_)) => true,
127            (ValueType::UInt64, Value::UInt64(_)) => true,
128            (ValueType::Int64, Value::Int64(_)) => true,
129            (ValueType::Length, Value::UInt32(_)) => true,
130            (ValueType::Exponent, Value::Int32(_)) => true,
131            (ValueType::Mantissa, Value::Int64(_)) => true,
132            (ValueType::Decimal, Value::Decimal(_)) => true,
133            (ValueType::ASCIIString, Value::ASCIIString(_)) => true,
134            (ValueType::UnicodeString, Value::UnicodeString(_)) => true,
135            (ValueType::Bytes, Value::Bytes(_)) => true,
136            _ => false,
137        }
138    }
139}
140
141/// Represents current value of a field.
142#[derive(Debug, PartialEq, Clone)]
143pub enum Value {
144    UInt32(u32),
145    Int32(i32),
146    UInt64(u64),
147    Int64(i64),
148    Decimal(Decimal),
149    ASCIIString(String),
150    UnicodeString(String),
151    Bytes(Vec<u8>),
152}
153
154impl Value {
155    /// It is a dynamic error [ERR D11] if a string does not match the syntax.
156    /// # Errors
157    /// Returns error if string parse fails.
158    pub fn set_from_string(&mut self, s: &str) -> Result<()> {
159        match self {
160            Value::UInt32(_) => {
161                *self = Value::UInt32(s.parse()?);
162            }
163            Value::Int32(_) => {
164                *self = Value::Int32(s.parse()?);
165            }
166            Value::UInt64(_) => {
167                *self = Value::UInt64(s.parse()?);
168            }
169            Value::Int64(_) => {
170                *self = Value::Int64(s.parse()?);
171            }
172            Value::Decimal(_) => {
173                *self = Value::Decimal(Decimal::from_string(s)?);
174            }
175            Value::ASCIIString(_) => {
176                *self = Value::ASCIIString(s.to_string());
177            }
178            Value::UnicodeString(_) => {
179                *self = Value::UnicodeString(s.to_string());
180            }
181            // The string is interpreted as an even number of hexadecimal digits [0-9A-Fa-f] possibly interleaved
182            // with whitespace. The literal is turned into a byte vector by first stripping any whitespace.
183            // Then each pair of characters is interpreted as a hexadecimal number representing a single byte.
184            Value::Bytes(_) => {
185                *self = Value::Bytes(string_to_bytes(s)?);
186            }
187        }
188        Ok(())
189    }
190
191    /// Applies delta to the current value and returns new value.
192    /// # Errors
193    /// Returns error if types are not bytes/string or previous and current types mismatch.
194    pub fn apply_delta(&self, delta: &Value, sub: i32) -> Result<Value> {
195        fn sub2index(sub: i32, len: usize) -> Result<(bool, usize)> {
196            // A negative subtraction length is used to remove values from the front of the string.
197            // Negative zero is used to append values to the front of the string.
198            let front: bool;
199            let mut i: usize;
200            if sub < 0 {
201                front = true;
202                i = (-sub - 1) as usize;
203            } else {
204                front = false;
205                i = sub as usize;
206            }
207            if i > len {
208                return Err(Error::Dynamic(format!(
209                    "subtraction length ({i}) is larger than string length ('{len}')"
210                ))); // [ERR D7]
211            }
212            if !front {
213                i = len - i;
214            }
215            Ok((front, i))
216        }
217
218        fn bytes_delta(v: &[u8], d: &[u8], sub: i32) -> Result<Vec<u8>> {
219            let (front, i) = sub2index(sub, v.len())?;
220            let mut b = Vec::with_capacity(v.len() + d.len());
221            if front {
222                b.extend_from_slice(d);
223                b.extend_from_slice(&v[i..]);
224            } else {
225                b.extend_from_slice(&v[..i]);
226                b.extend_from_slice(d);
227            }
228            Ok(b)
229        }
230
231        match (self, &delta) {
232            (Value::UInt32(v), Value::Int64(d)) => {
233                if *d < 0 {
234                    Ok(Value::UInt32(*v - (-*d) as u32))
235                } else {
236                    Ok(Value::UInt32(*v + *d as u32))
237                }
238            }
239            (Value::Int32(v), Value::Int64(d)) => Ok(Value::Int32(*v + *d as i32)),
240            (Value::UInt64(v), Value::Int64(d)) => {
241                if *d < 0 {
242                    Ok(Value::UInt64(*v - (-*d) as u64))
243                } else {
244                    Ok(Value::UInt64(*v + *d as u64))
245                }
246            }
247            (Value::Int64(v), Value::Int64(d)) => Ok(Value::Int64(*v + *d)),
248            (Value::ASCIIString(v), Value::ASCIIString(d)) => {
249                let (front, i) = sub2index(sub, v.len())?;
250                let s = if front {
251                    format!("{}{}", d, &v[i..])
252                } else {
253                    format!("{}{}", &v[..i], d)
254                };
255                Ok(Value::ASCIIString(s))
256            }
257            (Value::Bytes(v), Value::Bytes(d)) => Ok(Value::Bytes(bytes_delta(v, d, sub)?)),
258            (Value::UnicodeString(v), Value::Bytes(d)) => {
259                let b = bytes_delta(v.as_bytes(), d, sub)?;
260                let s = String::from_utf8(b)?; // [ERR R2]
261                Ok(Value::UnicodeString(s))
262            }
263            _ => Err(Error::Runtime(format!(
264                "Cannot apply delta {delta:?} to {self:?}"
265            ))),
266        }
267    }
268
269    /// Applies tail to the current value and returns new value.
270    /// # Errors
271    /// Returns error if types are not bytes/string or previous and current types mismatch.
272    pub fn apply_tail(&self, tail: &Value) -> Result<Value> {
273        let len: usize = match (self, tail) {
274            (Value::ASCIIString(v), Value::ASCIIString(t)) => min(t.len(), v.len()),
275            (Value::UnicodeString(v), Value::Bytes(t)) => min(t.len(), v.len()),
276            (Value::Bytes(v), Value::Bytes(t)) => min(t.len(), v.len()),
277            _ => {
278                return Err(Error::Runtime(format!(
279                    "Cannot apply tail {tail:?} to {self:?}"
280                )));
281            }
282        };
283        self.apply_delta(tail, len as i32)
284    }
285
286    /// Increments underlying integer value.
287    /// # Errors
288    /// Returns error if self type is not an integer.
289    pub fn apply_increment(&self) -> Result<Value> {
290        match self {
291            Value::UInt32(v) => Ok(Value::UInt32(v + 1)),
292            Value::Int32(v) => Ok(Value::Int32(v + 1)),
293            Value::UInt64(v) => Ok(Value::UInt64(v + 1)),
294            Value::Int64(v) => Ok(Value::Int64(v + 1)),
295            _ => Err(Error::Runtime(format!(
296                "Cannot apply increment to {self:?}"
297            ))),
298        }
299    }
300
301    /// Searches difference between current and previous value.
302    #[must_use]
303    pub fn find_delta(&self, prev: &Value) -> (Value, i32) {
304        match (self, prev) {
305            (Value::Int32(v), Value::Int32(p)) => (Value::Int64(i64::from(v - p)), 0),
306            (Value::Int64(v), Value::Int64(p)) => (Value::Int64(v - p), 0),
307            (Value::UInt32(v), Value::UInt32(p)) => {
308                (Value::Int64(i64::from(*v) - i64::from(*p)), 0)
309            }
310            (Value::UInt64(v), Value::UInt64(p)) => {
311                if *v < *p {
312                    (Value::Int64(-((*p - *v) as i64)), 0)
313                } else {
314                    (Value::Int64((*v - *p) as i64), 0)
315                }
316            }
317            (Value::ASCIIString(v), Value::ASCIIString(p)) => {
318                let (delta, sub) = string_delta(p, v);
319                (Value::ASCIIString(delta.to_string()), sub)
320            }
321            (Value::UnicodeString(v), Value::UnicodeString(p)) => {
322                let (delta, sub) = bytes_delta(p.as_bytes(), v.as_bytes());
323                (Value::Bytes(delta.to_vec()), sub)
324            }
325            (Value::Bytes(v), Value::Bytes(p)) => {
326                let (delta, sub) = bytes_delta(p, v);
327                (Value::Bytes(delta.to_vec()), sub)
328            }
329            _ => unimplemented!(),
330        }
331    }
332
333    /// Searches tail difference between current value and prev string or byte-slices.
334    /// # Errors
335    /// Returns error if current len is less than previous.
336    pub fn find_tail(&self, prev: &Value) -> Result<Value> {
337        match (self, prev) {
338            (Value::ASCIIString(v), Value::ASCIIString(p)) => {
339                let tail = string_tail(p, v)?;
340                Ok(Value::ASCIIString(tail.to_string()))
341            }
342            (Value::UnicodeString(v), Value::UnicodeString(p)) => {
343                let tail = bytes_tail(p.as_bytes(), v.as_bytes())?;
344                Ok(Value::Bytes(tail.to_vec()))
345            }
346            (Value::Bytes(v), Value::Bytes(p)) => {
347                let tail = bytes_tail(p, v)?;
348                Ok(Value::Bytes(tail.to_vec()))
349            }
350            _ => unimplemented!(),
351        }
352    }
353}
354
355impl Display for Value {
356    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
357        match self {
358            Value::UInt32(v) => f.write_fmt(format_args!("{v}")),
359            Value::Int32(v) => f.write_fmt(format_args!("{v}")),
360            Value::UInt64(v) => f.write_fmt(format_args!("{v}")),
361            Value::Int64(v) => f.write_fmt(format_args!("{v}")),
362            Value::Decimal(v) => f.write_fmt(format_args!("{v}")),
363            Value::ASCIIString(s) => f.write_str(s),
364            Value::UnicodeString(s) => f.write_fmt(format_args!("{s}")),
365            Value::Bytes(b) => {
366                let mut s = String::with_capacity(2 * b.len());
367                for v in b {
368                    let _ = write!(&mut s, "{v:02x}");
369                }
370                f.write_fmt(format_args!("{s}"))
371            }
372        }
373    }
374}