rof_rs/object_format/data_value/
hashmap.rs

1// Hashmap
2
3use std::collections::HashMap;
4
5use crate::object_format::{
6    ignore_str_split::{
7        ignoring_compliant_split_once, ignoring_compliant_split_str, SplitIgnoreRule,
8        SplitIgnoreRuleType,
9    },
10    property::{data_value_from_string, property_type::PropertyType},
11    DataValue,
12};
13
14#[derive(Debug)]
15pub struct DataValueHashmap {
16    key_type: PropertyType,
17    value_type: PropertyType,
18    properties: HashMap<Box<dyn DataValue>, Box<dyn DataValue>>,
19}
20
21impl DataValueHashmap {
22    pub fn new(
23        key_type: PropertyType,
24        value_type: PropertyType,
25        properties: HashMap<Box<dyn DataValue>, Box<dyn DataValue>>,
26    ) -> Self {
27        Self {
28            key_type,
29            value_type,
30            properties,
31        }
32    }
33}
34
35impl DataValue for DataValueHashmap {
36    fn serialize(
37        &self,
38        pretty_print: bool,
39        tab_index: usize,
40    ) -> (
41        PropertyType, /* serialized type */
42        String,       /* serialized value */
43    ) {
44        (
45            PropertyType::complex(
46                String::from("hashmap"),
47                vec![self.key_type.clone(), self.value_type.clone()],
48            ),
49            match pretty_print {
50                true => format!(
51                    "{{\n{}\n{}}}",
52                    self.properties
53                        .iter()
54                        .map(|(property_key, property_value)| format!(
55                            "{}{}: {};",
56                            "\t".repeat(tab_index + 1),
57                            property_key.serialize(pretty_print, tab_index).1,
58                            property_value.serialize(pretty_print, tab_index).1
59                        ))
60                        .collect::<Vec<String>>()
61                        .join("\n"),
62                    "\t".repeat(tab_index)
63                ),
64                false => format!(
65                    "{{{}}}",
66                    self.properties
67                        .iter()
68                        .map(|(property_key, property_value)| format!(
69                            "{}:{};",
70                            property_key.serialize(pretty_print, tab_index).1,
71                            property_value.serialize(pretty_print, tab_index).1
72                        ))
73                        .collect::<Vec<String>>()
74                        .join("")
75                ),
76            },
77        )
78    }
79
80    fn deserialize(
81        serialized_type: &PropertyType,
82        serialized_value: &str,
83    ) -> Option<Box<dyn DataValue>>
84    where
85        Self: Sized,
86    {
87        if !(serialized_type.get_base_type() == "hashmap"
88            && serialized_type.get_sub_types().len() == 2)
89        {
90            return None;
91        }
92
93        if !(serialized_value.starts_with("{")
94            && serialized_value.ends_with("}")
95            && serialized_value.chars().count() > 1)
96        {
97            return None;
98        }
99
100        let mut properties: HashMap<Box<dyn DataValue>, Box<dyn DataValue>> = HashMap::new();
101
102        for serialized_property in ignoring_compliant_split_str(
103            &serialized_value[1..serialized_value.len() - 1].trim(),
104            ';',
105            true,
106            vec![
107                SplitIgnoreRule::new(SplitIgnoreRuleType::PAIR('"')).set_ecapsulates_raw_text(true),
108                SplitIgnoreRule::new(SplitIgnoreRuleType::PAIR('\''))
109                    .set_ecapsulates_raw_text(true),
110                SplitIgnoreRule::new(SplitIgnoreRuleType::NEST('{', '}')),
111            ],
112        ) {
113            if serialized_property.trim().len() < 1 {
114                continue;
115            }
116
117            if let Some((serialized_key, serialized_value)) = ignoring_compliant_split_once(
118                &serialized_property,
119                ':',
120                true,
121                vec![
122                    SplitIgnoreRule::new(SplitIgnoreRuleType::PAIR('"'))
123                        .set_ecapsulates_raw_text(true),
124                    SplitIgnoreRule::new(SplitIgnoreRuleType::PAIR('\''))
125                        .set_ecapsulates_raw_text(true),
126                    SplitIgnoreRule::new(SplitIgnoreRuleType::NEST('{', '}')),
127                ],
128            ) {
129                properties.insert(
130                    data_value_from_string(
131                        serialized_type.get_sub_types().get(0).unwrap(),
132                        &serialized_key.trim(),
133                    ),
134                    data_value_from_string(
135                        serialized_type.get_sub_types().get(1).unwrap(),
136                        &serialized_value.trim(),
137                    ),
138                );
139            }
140        }
141
142        Some(Box::new(Self::new(
143            serialized_type.get_sub_types().get(0).unwrap().clone(),
144            serialized_type.get_sub_types().get(1).unwrap().clone(),
145            properties,
146        )))
147    }
148
149    fn clone_data_value(&self) -> Box<dyn DataValue> {
150        let mut cloned_properties: HashMap<Box<dyn DataValue>, Box<dyn DataValue>> = HashMap::new();
151
152        for (property_key, property_value) in self.properties.iter() {
153            cloned_properties.insert(
154                property_key.clone_data_value(),
155                property_value.clone_data_value(),
156            );
157        }
158
159        Box::new(Self::new(
160            self.key_type.clone(),
161            self.value_type.clone(),
162            cloned_properties,
163        ))
164    }
165
166    fn as_hashmap(&self) -> HashMap<Box<dyn DataValue>, Box<dyn DataValue>> {
167        let mut hashmap: HashMap<Box<dyn DataValue>, Box<dyn DataValue>> = HashMap::new();
168
169        for (property_key, property_value) in self.properties.iter() {
170            hashmap.insert(
171                property_key.clone_data_value(),
172                property_value.clone_data_value(),
173            );
174        }
175
176        hashmap
177    }
178}