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#[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 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 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 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#[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 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 Value::Bytes(_) => {
185 *self = Value::Bytes(string_to_bytes(s)?);
186 }
187 }
188 Ok(())
189 }
190
191 pub fn apply_delta(&self, delta: &Value, sub: i32) -> Result<Value> {
195 fn sub2index(sub: i32, len: usize) -> Result<(bool, usize)> {
196 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 ))); }
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)?; Ok(Value::UnicodeString(s))
262 }
263 _ => Err(Error::Runtime(format!(
264 "Cannot apply delta {delta:?} to {self:?}"
265 ))),
266 }
267 }
268
269 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 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 #[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 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}