dfx_base/
field_map.rs

1use chrono::DateTime;
2use chrono::Utc;
3
4use crate::FixChecksum;
5use crate::FixLength;
6use crate::fields::converters::IntoBytes;
7use crate::fields::converters::TryFrom;
8use crate::fields::ConversionError;
9use crate::message::Message;
10use crate::tags;
11use std::collections::BTreeMap;
12use std::collections::BTreeSet;
13use std::collections::HashMap;
14use std::num::Wrapping;
15use std::ops::{Deref, DerefMut};
16
17#[derive(Default, Clone, Debug)]
18pub struct FieldMap {
19    // fields: BTreeMap<Tag, Field>,
20    fields: BTreeMap<Tag, Field>,
21    groups: HashMap<Tag, Vec<Group>>,
22    // fields: HashMap<Tag, Field>,
23    // groups: HashMap<Tag, Vec<Group>>,
24    repeated_tags: Vec<Field>,
25    _field_order: FieldOrder,
26}
27
28pub type Tag = i32;
29pub type Total = u32;
30pub type Length = u32;
31pub type FieldOrder = Vec<Tag>;
32pub(crate) type FieldBase = Field;
33// pub type FieldValue = Vec<u8>;
34pub type FieldValue = std::sync::Arc<[u8]>;
35
36#[derive(Clone, Debug)]
37pub enum FieldMapError {
38    FieldNotFound(Tag),
39    ConversionError(ConversionError),
40}
41
42impl From<ConversionError> for FieldMapError {
43    fn from(err: ConversionError) -> Self {
44        FieldMapError::ConversionError(err)
45    }
46}
47
48#[derive(Default, Clone, Debug)]
49pub struct Group {
50    delim: Tag,
51    field: Tag,
52    map: FieldMap,
53    field_order: Option<FieldOrder>,
54}
55impl Group {
56    pub fn new(field: Tag, delim: Tag) -> Self {
57        Group {
58            delim,
59            field,
60            map: FieldMap::default(),
61            field_order: None,
62        }
63    }
64    pub fn delim(&self) -> Tag {
65        self.delim
66    }
67    pub fn field(&self) -> Tag {
68        self.field
69    }
70    pub fn calculate_string(&self) -> String {
71        if let Some(order) = &self.field_order {
72            todo!("calculate order: {:?}", order)
73        } else {
74            let order: Vec<Tag> = vec![self.delim];
75            self.map.calculate_string(Some(order))
76        }
77    }
78}
79impl Deref for Group {
80    type Target = FieldMap;
81    fn deref(&self) -> &Self::Target {
82        &self.map
83    }
84}
85
86impl DerefMut for Group {
87    fn deref_mut(&mut self) -> &mut Self::Target {
88        &mut self.map
89    }
90}
91#[derive(Clone, Debug, PartialEq, Eq)]
92pub struct Field(Tag, FieldValue);
93impl Default for Field {
94    fn default() -> Self {
95        Self(Default::default(), vec![].into())
96    }
97}
98
99impl Field {
100    pub fn new<'a, T: IntoBytes<FieldValue> + TryFrom<&'a FieldValue, Error = ConversionError>>(tag: Tag, value: T) -> Self {
101        Field(tag, value.as_bytes())
102    }
103    pub fn from_bytes(tag: Tag, value: std::sync::Arc<[u8]>) -> Self {
104        Field(tag, value)
105    }
106    pub fn tag(&self) -> Tag {
107        self.0
108    }
109    pub fn value(&self) -> &FieldValue {
110        &self.1
111    }
112    pub(crate) fn string_value(&self) -> Result<String, ConversionError> {
113        self.as_value()
114    }
115    pub(crate) fn to_string_field(&self) -> String {
116        format!("{}={}", self.tag(), self.as_value::<&str>().ok().unwrap_or(""))
117    }
118    pub fn as_value<'a, T>(&'a self) -> Result<T, ConversionError>
119    where
120        T: TryFrom<&'a FieldValue, Error = ConversionError>,
121    {
122        TryFrom::try_from(&self.1)
123    }
124
125    pub(crate) fn to_usize(&self) -> Option<usize> {
126        self.string_value().ok().map(|v| match v.parse::<usize>() {
127            Ok(value) => Some(value),
128            Err(_) => None,
129        }).flatten()
130    }
131}
132
133impl FixChecksum for &Field {
134    fn checksum(self) -> std::num::Wrapping<u8> {
135        self.tag().checksum() +
136        Wrapping(b'=' as u8) +
137        self.value().checksum() +
138        Wrapping(1) //incl SOH
139    }
140}
141
142impl FixLength for &Field {
143    fn bytes_len(self) -> u32 {
144        self.tag().bytes_len() +
145        1 + // =
146        self.value().bytes_len() +
147        1 //incl SOH
148    }
149}
150
151impl FieldMap {
152    pub fn from_field_order(_field_order: FieldOrder) -> Self {
153        let fields = Default::default();
154        let groups = Default::default();
155        let repeated_tags = Vec::default();
156        FieldMap {
157            fields,
158            groups,
159            repeated_tags,
160            _field_order,
161        }
162    }
163
164    pub fn from_field_map(src: &FieldMap) -> Self {
165        src.clone()
166    }
167
168    pub fn set_field_base(&mut self, field: Field, overwrite: Option<bool>) -> bool {
169        if matches!(overwrite, Some(b) if !b) && self.fields.contains_key(&field.tag()) {
170            return false;
171        }
172        self.fields.insert(field.tag(), field);
173        true
174    }
175
176    pub fn set_field_deref<F: Deref<Target = Field> + Clone>(
177        &mut self,
178        field: F,
179        overwrite: Option<bool>,
180    ) -> bool {
181        if matches!(overwrite, Some(b) if b) {
182            return false;
183        }
184        let field: &Field = &field;
185        self.fields.insert(field.tag(), field.clone());
186        true
187    }
188
189    pub fn set_tag_value<'a, T: IntoBytes<FieldValue>>(&mut self, tag: Tag, value: T) {
190        let field_base = Field(tag, value.as_bytes());
191        self.set_field_base(field_base, None);
192    }
193
194    pub fn set_field<'a, T: Into<Field>>(&mut self, field: T) {
195        self.set_field_base(field.into(), None);
196    }
197
198    pub fn get_field(&self, tag: Tag) -> Option<&Field> {
199        self.fields.get(&tag)
200    }
201
202    // VALUES
203    pub fn get_int(&self, tag: Tag) -> Result<u32, FieldMapError> {
204        match self.fields.get(&tag) {
205            None => Err(FieldMapError::FieldNotFound(tag)),
206            Some(value) => Ok(value.as_value()?),
207        }
208    }
209    pub fn get_string(&self, tag: Tag) -> Result<String, FieldMapError> {
210        match self.fields.get(&tag) {
211            None => Err(FieldMapError::FieldNotFound(tag)),
212            Some(value) => Ok(value.string_value()?),
213        }
214    }
215    pub fn get_string_unchecked(&self, tag: Tag) -> String {
216        self.fields[&tag].string_value().unwrap().into() // explicit_unchecked
217    }
218    pub fn get_bool(&self, tag: Tag) -> bool {
219        self.fields[&tag].string_value().ok() == Some("Y".into())
220    }
221    pub fn get_datetime(&self, tag: Tag) -> Result<DateTime<Utc>, ConversionError> {
222        self.fields[&tag].as_value()
223    }
224    // VALUES
225
226    pub fn get_field_mut(&mut self, tag: Tag) -> Option<&mut Field> {
227        self.fields.get_mut(&tag)
228    }
229    pub fn is_field_set(&self, tag: Tag) -> bool {
230        self.fields.contains_key(&tag)
231    }
232    pub fn remove_field(&mut self, tag: Tag) {
233        self.fields.remove(&tag);
234    }
235
236    // Groups
237    pub fn add_group(&mut self, _tag: Tag, group: &Group, set_count: Option<bool>) {
238        self.groups.entry(group.field()).or_insert_with(Vec::new);
239        self.groups
240            .get_mut(&group.field())
241            .unwrap() //checked
242            .push(group.clone());
243
244        if set_count.unwrap_or(true) {
245            // increment group size
246
247            let groupsize = self.groups[&group.field()].len();
248            let counttag = group.field();
249            // count = new IntField(couttag, groupsize);
250            let count = Field::new(counttag, format!("{}", groupsize));
251
252            self.set_field_base(count, Some(true));
253        }
254    }
255    /// index: Index in group starting at 1
256    /// field: Field Tag (Tag of field which contains count of group)
257    pub fn get_group(&self, index: u32, field: Tag) -> Result<&Group, FieldMapError> {
258        if !self.groups.contains_key(&field) {
259            return Err(FieldMapError::FieldNotFound(field));
260        }
261        if index == 0 {
262            return Err(FieldMapError::FieldNotFound(field));
263        }
264        if self.groups[&field].len() < index as usize {
265            return Err(FieldMapError::FieldNotFound(field));
266        }
267
268        Ok(&self.groups[&field][(index-1) as usize])
269    }
270    /// index: Index in group starting at 1
271    /// field: Field Tag (Tag of field which contains count of group)
272    pub fn get_group_mut(&mut self, index: u32, field: Tag) -> Result<&mut Group, FieldMapError> {
273        if !self.groups.contains_key(&field) {
274            return Err(FieldMapError::FieldNotFound(field));
275        }
276        if index == 0 {
277            return Err(FieldMapError::FieldNotFound(field));
278        }
279        if self.groups[&field].len() < index as usize {
280            return Err(FieldMapError::FieldNotFound(field));
281        }
282
283        //TODO (index - 1) try into usize => field not found
284        Ok(&mut self.groups.get_mut(&field).ok_or_else(|| FieldMapError::FieldNotFound(field))?[index as usize - 1])
285    }
286    /// index: Index in group starting at 1
287    /// field: Field Tag (Tag of field which contains count of group)
288    pub fn remove_group(&mut self, index: u32, field: Tag) -> Result<(), FieldMapError> {
289        if !self.groups.contains_key(&field) {
290            return Err(FieldMapError::FieldNotFound(field));
291        }
292        if index == 0 {
293            return Err(FieldMapError::FieldNotFound(field));
294        }
295        if self.groups[&field].len() < index as usize {
296            return Err(FieldMapError::FieldNotFound(field));
297        }
298
299        if self.groups[&field].len() == 1 {
300            self.groups.remove(&field);
301        } else {
302            self.groups
303                .get_mut(&field)
304                .ok_or_else(|| FieldMapError::FieldNotFound(field))?
305                //TODO (index - 1) try into usize => field not found
306                .remove((index as usize) - 1);
307        }
308        Ok(())
309    }
310    pub fn replace_group(
311        &mut self,
312        index: Tag,
313        field: Tag,
314        group: Group,
315    ) -> Result<Group, FieldMapError> {
316        if !self.groups.contains_key(&field) {
317            return Err(FieldMapError::FieldNotFound(field));
318        }
319        if index == 0 {
320            return Err(FieldMapError::FieldNotFound(field));
321        }
322        if self.groups[&field].len() < index as usize {
323            return Err(FieldMapError::FieldNotFound(field));
324        }
325
326        let group_ref = self
327            .groups
328            .get_mut(&field)
329            .ok_or_else(|| FieldMapError::FieldNotFound(field))?
330            //TODO (index - 1) try into usize => field not found
331            .get_mut(index as usize - 1)
332            .ok_or_else(|| FieldMapError::FieldNotFound(field))?;
333        let group = std::mem::replace(group_ref, group);
334
335        Ok(group)
336    }
337
338    pub fn group_tags(&self) -> impl Iterator<Item = &Tag> {
339        self.groups.keys()
340    }
341
342    pub fn group_count(&self, field: Tag) -> Result<usize, FieldMapError> {
343        if !self.groups.contains_key(&field) {
344            return Err(FieldMapError::FieldNotFound(field));
345        }
346        Ok(self.groups[&field].len())
347    }
348
349    pub fn is_empty(&self) -> bool {
350        self.fields.len() == 0 && self.groups.len() == 0
351    }
352
353    pub fn calculate_total(&self) -> Total {
354        let mut total = 0;
355        for field in self.fields.values() {
356            if field.tag() != tags::CheckSum {
357                total += field.checksum().0 as Total;
358            }
359        }
360
361        for field in self.repeated_tags() {
362            if field.tag() != tags::CheckSum {
363                total += field.checksum().0 as Total;
364            }
365        }
366
367        for group_list in self.groups.values() {
368            for group in group_list {
369                total += group.calculate_total();
370            }
371        }
372        total
373    }
374
375    pub fn len(&self) -> Length {
376        let mut total = 0;
377        for field in self.fields.values() {
378            if field.tag() != tags::CheckSum
379                && field.tag() != tags::BeginString
380                && field.tag() != tags::BodyLength
381            {
382                total += field.bytes_len();
383            }
384        }
385
386        for field in self.repeated_tags() {
387            if field.tag() != tags::CheckSum
388                && field.tag() != tags::BeginString
389                && field.tag() != tags::BodyLength
390            {
391                total += field.bytes_len();
392            }
393        }
394
395        for group_list in self.groups.values() {
396            for group in group_list {
397                total += group.len();
398            }
399        }
400
401        total
402    }
403
404    pub fn repeated_tags(&self) -> &Vec<Field> {
405        &self.repeated_tags
406    }
407
408    pub fn repeated_tags_mut(&mut self) -> &mut Vec<Field> {
409        &mut self.repeated_tags
410    }
411
412    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Tag, &Field)> {
413        self.fields.iter()
414    }
415
416    pub fn clear(&mut self) {
417        self.fields.clear();
418        self.groups.clear();
419    }
420
421    pub fn calculate_string(&self, prefields: Option<FieldOrder>) -> String {
422        let group_counter_tags: BTreeSet<&Tag> = self.group_tags().collect();
423        let prefields = prefields.unwrap_or_default();
424        let mut sb = String::new();
425
426        for prefield in &prefields {
427            if self.is_field_set(*prefield) {
428                sb.push_str(
429                    format!(
430                        "{}={}{}",
431                        prefield,
432                        self.get_string_unchecked(*prefield),
433                        Message::SOH
434                    )
435                    .as_str(),
436                );
437                if group_counter_tags.contains(prefield) {
438                    let glist = &self.groups[prefield];
439                    for g in glist {
440                        sb.push_str(&g.calculate_string());
441                    }
442                }
443            }
444        }
445
446        for field in self.fields.values() {
447            if group_counter_tags.contains(&field.tag()) {
448                continue;
449            }
450            if prefields.contains(&field.tag()) {
451                continue; //already did this one
452            }
453            sb.push_str(
454                format!("{}={}{}", field.tag(), field.string_value().unwrap(), Message::SOH).as_str(),
455            );
456        }
457
458        for counter_tag in self.groups.keys() {
459            if prefields.contains(counter_tag) {
460                continue; //already did this one
461            }
462
463            let grouplist = &self.groups[counter_tag];
464            if grouplist.is_empty() {
465                continue; //probably unnecessary, but it doesn't hurt to check
466            }
467
468            sb.push_str(
469                format!(
470                    "{}{}",
471                    self.fields[counter_tag].to_string_field(),
472                    Message::SOH
473                )
474                .as_str(),
475            );
476
477            for group in grouplist {
478                sb.push_str(&group.calculate_string());
479            }
480        }
481
482        sb
483    }
484}
485
486#[cfg(test)]
487mod tests {
488    use super::FieldValue;
489    use super::Tag;
490    use std::any::Any;
491    use std::any::TypeId;
492
493    trait TagValue: Any {
494        fn tag(&self) -> Tag;
495        fn value(&self) -> &FieldValue;
496        fn as_any(&self) -> &dyn Any;
497    }
498
499    #[derive(Debug)]
500    struct Test {
501        pub tag: Tag,
502        pub value: FieldValue,
503    }
504    impl TagValue for Test {
505        fn tag(&self) -> Tag {
506            self.tag
507        }
508        fn value(&self) -> &FieldValue {
509            &self.value
510        }
511        fn as_any(&self) -> &dyn Any {
512            self
513        }
514    }
515    impl<T: TagValue> From<T> for Box<dyn TagValue> {
516        fn from(tag_value: T) -> Self {
517            Box::new(tag_value)
518        }
519    }
520
521    #[test]
522    fn box_test() {
523        let boxed = Test {
524            tag: 0,
525            value: "Hello".as_bytes().into(),
526        }
527        .into();
528        let boxed_vec: Vec<Box<dyn TagValue>> = vec![boxed];
529        for value in boxed_vec {
530            let value: &dyn TagValue = &*value;
531            if value.type_id() == TypeId::of::<Test>() {
532                let result = value.as_any().downcast_ref::<Test>();
533                assert!(result.is_some());
534            } else {
535                panic!()
536            }
537        }
538    }
539}