1use bytes::Bytes;
4use chrono::{NaiveDate, NaiveDateTime};
5
6use crate::msg::tvf::{Tvf, TvfError};
7use std::{borrow::Cow, collections::hash_map::HashMap};
8
9#[derive(Debug, Default, Clone, PartialEq, Eq)]
11pub struct SimpleStringTvf {
12 fields: HashMap<usize, String>,
13}
14
15static SIMPLE_DATE_FMT: &str = "%Y-%m-%d";
16static SIMPLE_DATETIME_FMT: &str = "%Y-%m-%dT%H:%M:%S";
17
18impl Tvf for SimpleStringTvf {
20 fn is_empty(&self) -> bool {
33 self.fields.is_empty()
34 }
35
36 fn len(&self) -> usize {
51 self.fields.len()
52 }
53
54 fn contains(&self, id: usize) -> bool {
55 self.fields.contains_key(&id)
56 }
57
58 fn remove(&mut self, id: usize) {
59 self.fields.remove(&id);
60 }
61
62 fn into_keys(self) -> Vec<usize> {
63 self.fields.into_keys().collect::<_>()
64 }
65
66 fn keys(&self) -> Vec<usize> {
67 self.fields.keys().cloned().collect()
68 }
69
70 fn get_buffer(&self, id: usize) -> Result<Cow<'_, SimpleStringTvf>, TvfError> {
71 match self.fields.get(&id) {
72 Some(str_value) => Ok(Cow::Owned(SimpleStringTvf::deserialize(str_value)?)),
73 None => Err(TvfError::FieldNotFound(id)),
74 }
75 }
76
77 fn get_unsigned(&self, id: usize) -> Result<u64, TvfError> {
78 match self.fields.get(&id) {
79 Some(str_value) => match str_value.parse::<u64>() {
80 Ok(value) => Ok(value),
81 Err(_) => Err(TvfError::TypeMismatch),
82 },
83 None => Err(TvfError::FieldNotFound(id)),
84 }
85 }
86
87 fn get_signed(&self, id: usize) -> Result<i64, TvfError> {
88 match self.fields.get(&id) {
89 Some(str_value) => match str_value.parse::<i64>() {
90 Ok(value) => Ok(value),
91 Err(_) => Err(TvfError::TypeMismatch),
92 },
93 None => Err(TvfError::FieldNotFound(id)),
94 }
95 }
96
97 fn get_byte(&self, id: usize) -> Result<u8, TvfError> {
98 match self.fields.get(&id) {
99 Some(str_value) => match hex::decode(str_value) {
100 Ok(bytes) => Ok(bytes[0]),
101 Err(_) => Err(TvfError::TypeMismatch),
102 },
103 None => Err(TvfError::FieldNotFound(id)),
104 }
105 }
106
107 fn get_float(&self, id: usize) -> Result<f64, TvfError> {
108 match self.fields.get(&id) {
109 Some(str_value) => match str_value.parse::<f64>() {
110 Ok(value) => Ok(value),
111 Err(_) => Err(TvfError::TypeMismatch),
112 },
113 None => Err(TvfError::FieldNotFound(id)),
114 }
115 }
116
117 fn get_string(&self, id: usize) -> Result<Cow<'_, String>, TvfError> {
118 match self.fields.get(&id) {
119 Some(value) => Ok(Cow::Borrowed(value)),
120 None => Err(TvfError::FieldNotFound(id)),
121 }
122 }
123
124 fn get_bytes(&self, id: usize) -> Result<Cow<'_, Bytes>, TvfError> {
125 match self.fields.get(&id) {
126 Some(str_value) => match hex::decode(str_value) {
127 Ok(bytes) => Ok(Cow::Owned(Bytes::from(bytes))),
128 Err(_) => Err(TvfError::TypeMismatch),
129 },
130 None => Err(TvfError::FieldNotFound(id)),
131 }
132 }
133
134 fn get_date(&self, id: usize) -> Result<NaiveDate, TvfError> {
135 match self.fields.get(&id) {
136 Some(str_value) => match NaiveDate::parse_from_str(str_value, SIMPLE_DATE_FMT) {
137 Ok(d) => Ok(d),
138 Err(e) => Err(TvfError::ConvertionError(e.to_string())),
139 },
140 None => Err(TvfError::FieldNotFound(id)),
141 }
142 }
143
144 fn get_datetime(&self, id: usize) -> Result<NaiveDateTime, TvfError> {
145 match self.fields.get(&id) {
146 Some(str_value) => {
147 match NaiveDateTime::parse_from_str(str_value, SIMPLE_DATETIME_FMT) {
148 Ok(d) => Ok(d),
149 Err(e) => Err(TvfError::ConvertionError(e.to_string())),
150 }
151 }
152 None => Err(TvfError::FieldNotFound(id)),
153 }
154 }
155
156 fn put_buffer(&mut self, id: usize, buffer: SimpleStringTvf) {
167 self.fields.insert(id, buffer.serialize());
168 }
169
170 fn put_unsigned(&mut self, id: usize, unsigned: u64) {
171 self.fields.insert(id, unsigned.to_string());
172 }
173
174 fn put_signed(&mut self, id: usize, signed: i64) {
175 self.fields.insert(id, signed.to_string());
176 }
177
178 fn put_byte(&mut self, id: usize, byte: u8) {
179 let s = hex::encode(vec![byte]);
180 self.fields.insert(id, s);
181 }
182
183 fn put_float(&mut self, id: usize, float: f64) {
184 self.fields.insert(id, float.to_string());
185 }
186
187 fn put_string<T: Into<String>>(&mut self, id: usize, string: T) {
188 self.fields.insert(id, string.into());
189 }
190
191 fn put_bytes(&mut self, id: usize, buffer: bytes::Bytes) {
192 let s = hex::encode(buffer);
193 self.fields.insert(id, s);
194 }
195
196 fn put_date(&mut self, id: usize, date: chrono::NaiveDate) {
197 self.fields
198 .insert(id, date.format(SIMPLE_DATE_FMT).to_string());
199 }
200
201 fn put_datetime(&mut self, id: usize, datetime: chrono::NaiveDateTime) {
202 self.fields
203 .insert(id, datetime.format(SIMPLE_DATETIME_FMT).to_string());
204 }
205
206 }
210
211impl SimpleStringTvf {
212 pub fn serialize(&self) -> String {
214 let mut out_str = String::new();
215 for (k, v) in self.fields.iter() {
218 let len = v.len();
219 out_str.push_str(&format!("{k};{len};{v};"));
220 }
221
222 out_str
223 }
224
225 pub fn deserialize(serial: &str) -> Result<SimpleStringTvf, TvfError> {
227 let mut buffer: SimpleStringTvf = Default::default();
228 let mut w_serial = serial;
229
230 while let Some((k, lv)) = w_serial.split_once(';') {
231 let key = k
232 .parse::<usize>()
233 .map_err(|e| TvfError::SerializationError(e.to_string()))?;
234
235 if let Some((l, rest)) = lv.split_once(';') {
236 let len = l
237 .parse::<usize>()
238 .map_err(|e| TvfError::SerializationError(e.to_string()))?;
239 buffer.fields.insert(key, String::from(&rest[0..len]));
240 if rest.chars().nth(len) != Some(';') {
241 return Err(TvfError::SerializationError(
242 "Bad field termination char".into(),
243 ));
244 }
245 w_serial = &rest[len + 1..];
246 } else {
247 return Err(TvfError::SerializationError("No len after key".into()));
248 }
249 }
250
251 Ok(buffer)
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use crate::msg::tvf::TvfFilter;
258
259 use super::*;
260 use std::fmt::Debug;
261
262 fn test_tvf<T: Tvf + Default + Debug + PartialEq + Clone>(tvf: &mut T) {
263 let mut sub_buffer: T = Default::default();
264 sub_buffer.put_float(200, 154.5);
265 sub_buffer.put_string(201, "Hello rust!");
266 sub_buffer.remove(201);
267 assert!(!sub_buffer.contains(201));
268 sub_buffer.put_string(201, "Hello world!");
269 assert!(sub_buffer.contains(201));
270
271 assert!(tvf.is_empty());
272 tvf.put_unsigned(1, 42);
273 assert_eq!(1, tvf.len());
274 assert!(!tvf.contains(2));
275 tvf.put_string(2, String::from("The great string"));
276 assert!(tvf.contains(2));
277 tvf.put_signed(3, -1);
278 assert_eq!(-1, tvf.get_signed(3).unwrap());
279 tvf.put_float(5, 6.56);
280 tvf.put_byte(6, 32u8);
281 tvf.put_bytes(7, Bytes::from(hex::decode("aabb77ff").unwrap()));
282 tvf.put_date(8, NaiveDate::from_ymd_opt(2023, 6, 5).unwrap());
283 tvf.put_datetime(
284 9,
285 NaiveDate::from_ymd_opt(2023, 6, 5)
286 .unwrap()
287 .and_hms_opt(15, 2, 0)
288 .unwrap(),
289 );
290 tvf.put_buffer(10, sub_buffer.clone());
291 assert_eq!(Err(TvfError::TypeMismatch), tvf.get_unsigned(2));
292 assert_eq!(Err(TvfError::TypeMismatch), tvf.get_signed(2));
293 assert_eq!(Err(TvfError::TypeMismatch), tvf.get_float(2));
294 assert_eq!(Err(TvfError::TypeMismatch), tvf.get_byte(2));
295 assert_eq!(Err(TvfError::TypeMismatch), tvf.get_bytes(2));
296 assert_eq!(
297 Err(TvfError::ConvertionError(
298 "input contains invalid characters".to_string()
299 )),
300 tvf.get_date(2)
301 );
302 assert_eq!(
303 Err(TvfError::ConvertionError(
304 "input contains invalid characters".to_string()
305 )),
306 tvf.get_datetime(2)
307 );
308
309 assert_eq!(Ok(42), tvf.get_unsigned(1));
310 assert_eq!(
311 Ok(Cow::Borrowed(&String::from("The great string"))),
312 tvf.get_string(2)
313 );
314 assert_eq!(Ok(-1), tvf.get_signed(3));
315 assert_eq!(Err(TvfError::FieldNotFound(4)), tvf.get_float(4));
316 assert_eq!(Ok(6.56), tvf.get_float(5));
317 assert_eq!(Ok(32), tvf.get_byte(6));
318 assert_eq!(
319 Ok(Cow::Owned(Bytes::from(hex::decode("aabb77ff").unwrap()))),
320 tvf.get_bytes(7)
321 );
322 assert_eq!(
323 Ok(NaiveDate::parse_from_str("2023-06-05", SIMPLE_DATE_FMT).unwrap()),
324 tvf.get_date(8)
325 );
326 assert_eq!(
327 Ok(NaiveDateTime::parse_from_str("2023-06-05T15:02:00", SIMPLE_DATETIME_FMT).unwrap()),
328 tvf.get_datetime(9)
329 );
330 assert_eq!(Ok(Cow::Owned(sub_buffer)), tvf.get_buffer(10));
331
332 assert_eq!(Err(TvfError::FieldNotFound(100)), tvf.get_unsigned(100));
333 assert_eq!(Err(TvfError::FieldNotFound(110)), tvf.get_signed(110));
334 assert_eq!(Err(TvfError::FieldNotFound(120)), tvf.get_float(120));
335 assert_eq!(Err(TvfError::FieldNotFound(130)), tvf.get_string(130));
336 assert_eq!(Err(TvfError::FieldNotFound(140)), tvf.get_byte(140));
337 assert_eq!(Err(TvfError::FieldNotFound(150)), tvf.get_bytes(150));
338 assert_eq!(Err(TvfError::FieldNotFound(160)), tvf.get_date(160));
339 assert_eq!(Err(TvfError::FieldNotFound(170)), tvf.get_datetime(170));
340 assert_eq!(Err(TvfError::FieldNotFound(180)), tvf.get_buffer(180));
341 }
342
343 #[test]
344 fn test_simple_tvf() {
345 let mut simple_tvf: SimpleStringTvf = Default::default();
346 test_tvf(&mut simple_tvf);
347 assert!(!format!("{simple_tvf:?}").is_empty());
348 let keys = simple_tvf.keys();
349 let into_keys = simple_tvf.clone().into_keys();
350 assert_eq!(keys, into_keys);
351 assert_eq!(9, keys.len());
352 let serial = simple_tvf.serialize();
353 let unserial = SimpleStringTvf::deserialize(&serial).unwrap();
354 assert_eq!(simple_tvf, unserial);
355
356 assert_eq!(
357 Err(TvfError::SerializationError(
358 "invalid digit found in string".into()
359 )),
360 SimpleStringTvf::deserialize("jean;luc")
361 );
362 assert_eq!(
363 Err(TvfError::SerializationError("No len after key".into())),
364 SimpleStringTvf::deserialize("1;")
365 );
366 assert_eq!(
367 Err(TvfError::SerializationError(
368 "invalid digit found in string".into()
369 )),
370 SimpleStringTvf::deserialize("1;jean;")
371 );
372 assert_eq!(
373 Err(TvfError::SerializationError(
374 "Bad field termination char".into()
375 )),
376 SimpleStringTvf::deserialize("1;2;to,")
377 );
378 }
379
380 enum TvfTestFilter {}
381
382 impl TvfFilter for TvfTestFilter {
383 fn filter<T: Tvf>(mut buf: T) -> T {
384 buf = <TvfTestFilter as TvfFilter>::mask_tvf_str_field(buf, 1, "0");
385 buf
386 }
387 }
388
389 #[test]
390 fn test_tvf_filter() {
391 let mut simple_tvf: SimpleStringTvf = Default::default();
392 simple_tvf.put_string(1, "1234");
393 simple_tvf.put_string(2, "1234");
394 assert_eq!(2, simple_tvf.len());
395
396 simple_tvf = TvfTestFilter::filter(simple_tvf);
397 assert_eq!(2, simple_tvf.len());
398 assert_eq!("0000", simple_tvf.get_string(1).unwrap().as_str());
399 assert_eq!("1234", simple_tvf.get_string(2).unwrap().as_str());
400 }
401}