simple_direct_delta_encoding/
lib.rs

1mod data_difference;
2#[cfg(test)]
3mod data_difference_tests;
4#[cfg(test)]
5mod tests;
6
7use std::collections::BTreeMap;
8
9use data_difference::*;
10use dispnet_hash::{DispnetHash, HashType};
11
12#[derive(Debug)]
13pub enum SDDEError {
14    CRC(String),
15    DifferenceInvalid(String),
16}
17
18#[derive(Clone)]
19pub struct SimpleDirectDeltaEncoding {
20    pub data_collection: BTreeMap<u8, IndexedData>,
21    pub crc: Vec<u8>,
22    index_mapping: BTreeMap<u8, Vec<u8>>,
23    last_index_mapping: BTreeMap<u8, HistoryValue>,
24}
25
26#[derive(Debug, Clone, Default)]
27pub struct HistoryValue {
28    pub current: Vec<u8>,
29    pub last: Vec<u8>,
30}
31
32impl HistoryValue {
33    pub fn new(current: Vec<u8>) -> HistoryValue {
34        HistoryValue {
35            current,
36            last: Vec::new(),
37        }
38    }
39
40    pub fn set(&mut self, current: Vec<u8>) {
41        self.last = self.current.clone();
42        self.current = current;
43    }
44}
45
46#[derive(Debug, Clone)]
47pub struct IndexedData {
48    pub index: u8,
49    pub data: Vec<u8>,
50}
51
52impl IndexedData {
53    pub fn new(index: u8, data: Vec<u8>) -> IndexedData {
54        IndexedData { index, data }
55    }
56}
57
58#[derive(Debug, Default)]
59pub struct EntryDifference {
60    pub remove_entry: bool,
61    pub diffs: Vec<Difference>,
62    pub map_name_changed: Option<Vec<Difference>>,
63}
64
65impl EntryDifference {
66    pub fn new(diffs: Vec<Difference>) -> EntryDifference {
67        EntryDifference {
68            remove_entry: false,
69            diffs,
70            map_name_changed: None,
71        }
72    }
73
74    pub fn remove_entry() -> EntryDifference {
75        EntryDifference {
76            remove_entry: true,
77            diffs: Vec::new(),
78            map_name_changed: None,
79        }
80    }
81}
82
83#[derive(Debug, Clone)]
84pub struct IndexedDataResult {
85    pub index: u8,
86    pub data: Vec<u8>,
87    pub map_name_changed: Option<Vec<u8>>,
88}
89
90impl IndexedDataResult {
91    pub fn new(index_data: &IndexedData) -> IndexedDataResult {
92        IndexedDataResult {
93            index: index_data.index,
94            data: index_data.data.clone(),
95            map_name_changed: None,
96        }
97    }
98}
99
100impl SimpleDirectDeltaEncoding {
101    pub fn new(data: &[IndexedData]) -> SimpleDirectDeltaEncoding {
102        let data = Self::get_sorted(data);
103        let bytes = Self::fold_indexed_data(&data);
104        let crc = DispnetHash::create(HashType::CRC, &bytes, None);
105        let mut data_map: BTreeMap<u8, IndexedData> = BTreeMap::new();
106        for indexed_data in data {
107            data_map.insert(indexed_data.index, indexed_data.clone());
108        }
109        SimpleDirectDeltaEncoding {
110            data_collection: data_map,
111            crc: crc.digest_value.clone(),
112            index_mapping: BTreeMap::new(),
113            last_index_mapping: BTreeMap::new(),
114        }
115    }
116
117    pub fn load(data: &[IndexedData], crc: Vec<u8>) -> SimpleDirectDeltaEncoding {
118        let data = Self::get_sorted(data);
119        let mut data_map: BTreeMap<u8, IndexedData> = BTreeMap::new();
120        for indexed_data in data {
121            data_map.insert(indexed_data.index, indexed_data.clone());
122        }
123        SimpleDirectDeltaEncoding {
124            data_collection: data_map,
125            crc,
126            index_mapping: BTreeMap::new(),
127            last_index_mapping: BTreeMap::new(),
128        }
129    }
130
131    /// Current state of the data
132    /// 
133    /// 
134    /// * Indexed data and index mappings are stored in bytes
135    /// * The data is always in the same order (indexed data first, index mappings last ...)
136    pub fn get_state(&self) -> Vec<u8> {
137        let mut bytes = Self::fold_indexed_data(&self.data_collection.values().cloned().collect::<Vec<IndexedData>>());
138        for (_, value) in self.last_index_mapping.iter() {
139            bytes.extend(value.current.clone());
140        }
141        bytes
142    }
143
144    /// Change the index mapping for the given index
145    pub fn change_index_mapping(&mut self, index: u8, key: &[u8]) {
146        self.index_mapping.insert(index, key.to_owned());
147    }
148
149    /// Stores all index mappings in the last index mapping collection.
150    /// 
151    /// 
152    /// This is useful when the changed index mappings should not be included in the next patch.<br/>
153    /// After creating or applying a patch this same logic will be applied.
154    pub fn apply_index_mappings(&mut self) {
155        for (index, key) in self.index_mapping.iter() {
156            if let Some(value) = self.last_index_mapping.get_mut(index) {
157                value.set(key.to_owned());
158            } else {
159                self.last_index_mapping.insert(*index, HistoryValue::new(key.to_owned()));
160            }
161        }
162        self.index_mapping.clear();
163    }
164
165    /// Patch the data with the new data and return the diff data
166    ///
167    ///
168    /// The diff data is a byte array with the following format:<br/>
169    /// [CRC length, CRC value, Difference 1, Difference 2, ...]<br/>
170    /// * The CRC length is a single byte that represents the length of the CRC value
171    /// * The CRC value is the hash of the data before patching
172    /// * The Difference is a struct that represents the difference between the old and new data
173    ///
174    ///
175    /// The Difference is a byte array with the following format:
176    /// [Action, Range start, Range length, Value]
177    /// The Action is a single byte that represents the action that should be taken
178    /// The Range start is a variable length byte array that represents the start index of the range
179    /// The Range length is a variable length byte array that represents the length of the range
180    /// The Value is a variable length byte array that represents the value that should be inserted
181    /// The Value is only present in the Replace and Insert actions
182    pub fn patch(&mut self, new_data: &[IndexedData]) -> Vec<u8> {
183        let new_data = Self::get_sorted(new_data);
184        let new_indexes: Vec<u8> = new_data.iter().map(|x| x.index).collect();
185        // add the crc
186        let mut diff_data: Vec<u8> = vec![self.crc.len() as u8];
187        diff_data.extend(self.crc.clone());
188
189        for data in new_data {
190            if let Some(old_data) = self.data_collection.get_mut(&data.index) {
191                let last_diff = DataDifference::diff(&old_data.data, &data.data);
192                old_data.data = data.data.to_owned();
193
194                // create the diff data for the index
195                let mut new_diff = Vec::new();
196                // set the index
197                new_diff.push(b'v');
198                new_diff.push(data.index);
199                for diff in last_diff.iter() {
200                    let bytes = diff.to_bytes();
201                    // add the difference
202                    new_diff.extend(Difference::get_usize_type_to_bytes(bytes.len()));
203                    new_diff.extend(bytes);
204                }
205                // only add the diff if there are any changes to the data (first 2 bytes are the index)
206                if new_diff.len() > 2 {
207                    diff_data.extend(new_diff);
208                }
209            } else {
210                // add the new data entry
211                self.data_collection.insert(data.index, data.clone());
212                // create the diff data for the index
213                let mut new_diff = Vec::new();
214                // set the index
215                new_diff.push(b'v');
216                new_diff.push(data.index);
217                for diff in DataDifference::diff(&Vec::new(), &data.data).iter() {
218                    let bytes = diff.to_bytes();
219                    // add the difference
220                    new_diff.extend(Difference::get_usize_type_to_bytes(bytes.len()));
221                    new_diff.extend(bytes);
222                }
223                diff_data.extend(new_diff);
224            }
225        }
226
227        // check if there are indexes removed
228        let src_indexes: Vec<u8> = self.data_collection.keys().copied().collect();
229        let removed_indexes: Vec<u8> = src_indexes
230            .iter()
231            .filter(|x| !new_indexes.contains(x))
232            .copied()
233            .collect();
234
235        for index in &removed_indexes {
236            // remove the index from the data collection
237            self.data_collection.remove(index);
238
239            // add the remove index command to the patch
240            diff_data.extend(vec![b'v', index.to_owned(), b'r']);
241        }
242
243        // apply changes in the index mapping to the last index mapping
244        for (index, new_data) in self.index_mapping.iter() {
245            // ignore mappings for removed indexes
246            if removed_indexes.contains(index) {
247                continue;
248            }
249            // create the diff data for the index
250            // set the index and the control byte
251            let new_diff = vec![b'v', *index, b'm'];
252
253            let mut is_new_mapping = false;
254            // add the diff data for the index mapping to the patch
255            if let Some(old_value) = self.last_index_mapping.get(index) {
256                let last_diff = DataDifference::diff(&old_value.current, new_data);
257
258                let mut diff_only = Vec::new();
259                for diff in last_diff.iter() {
260                    let bytes = diff.to_bytes();
261                    // add the difference
262                    diff_only.extend(Difference::get_usize_type_to_bytes(bytes.len()));
263                    diff_only.extend(bytes);
264                }
265                // only add the diff if there are any changes to the data (first 2 bytes are the index)
266                if !diff_only.is_empty() {
267                    diff_data.extend(new_diff);
268                    diff_data.extend(Difference::get_usize_type_to_bytes(diff_only.len()));
269                    diff_data.extend(diff_only);
270                }
271            } else {
272                is_new_mapping = true;
273                // add the new data entry
274                let mut diff_only = Vec::new();
275                for diff in DataDifference::diff(&Vec::new(), new_data).iter() {
276                    let bytes = diff.to_bytes();
277                    // add the difference
278                    diff_only.extend(Difference::get_usize_type_to_bytes(bytes.len()));
279                    diff_only.extend(bytes);
280                }
281                diff_data.extend(new_diff);
282                diff_data.extend(Difference::get_usize_type_to_bytes(diff_only.len()));
283                diff_data.extend(diff_only);
284            }
285            // update the last index mapping
286            if is_new_mapping {
287                self.last_index_mapping
288                    .insert(*index, HistoryValue::new(new_data.clone()));
289            } else {
290                self.last_index_mapping
291                    .get_mut(index)
292                    .unwrap()
293                    .set(new_data.clone());
294            }
295        }
296        self.index_mapping.clear();
297
298        diff_data
299    }
300
301    pub fn apply_patch(&mut self, diff_data: &[u8]) -> Result<Vec<IndexedDataResult>, SDDEError> {
302        let crc_length = diff_data[0];
303        let crc_value = &diff_data[1..(1 + crc_length as usize)];
304        let bytes = Self::fold_indexed_data(
305            self.data_collection
306                .values()
307                .map(|x| x.to_owned())
308                .collect::<Vec<IndexedData>>()
309                .as_slice(),
310        );
311        let crc = DispnetHash::create(HashType::CRC, &bytes, None);
312        if crc.digest_value != crc_value {
313            return Err(SDDEError::CRC("CRC value does not match".to_owned()));
314        }
315
316        let mut return_data: Vec<IndexedDataResult> = Vec::new();
317        let diffs = Self::get_differences(diff_data);
318        for (index, diff) in diffs.iter() {
319            // the entry should be removed
320            if diff.remove_entry {
321                self.data_collection.remove(index);
322                continue;
323            }
324            if let Some(src_data) = self.data_collection.get_mut(index) {
325                let data = DataDifference::apply_diff(&src_data.data, &diff.diffs);
326                src_data.data = data;
327            } else {
328                // the index does not exist, add a new data entry
329                let new_data = Vec::new();
330                let data = DataDifference::apply_diff(&new_data, &diff.diffs);
331                let data = IndexedData::new(*index, data);
332                self.data_collection.insert(*index, data);
333            }
334
335            let mut index_data = IndexedDataResult::new(self.data_collection.get(index).unwrap());
336            // check if the map name has changes
337            if diff.map_name_changed.is_some() {
338                let last_index_map_bytes = self
339                    .last_index_mapping
340                    .get(index)
341                    .cloned()
342                    .unwrap_or_default()
343                    .current;
344                let map_diffs_bytes = DataDifference::apply_diff(
345                    &last_index_map_bytes,
346                    diff.map_name_changed.as_ref().unwrap(),
347                );
348                index_data.map_name_changed = Some(map_diffs_bytes.clone());
349                // update the last index mapping
350                if !self.last_index_mapping.contains_key(index) {
351                    self.last_index_mapping
352                        .insert(*index, HistoryValue::new(map_diffs_bytes));
353                } else {
354                    self.last_index_mapping
355                        .get_mut(index)
356                        .unwrap()
357                        .set(map_diffs_bytes);
358                }
359            }
360            return_data.push(index_data);
361        }
362
363        self.crc = crc.digest_value.clone();
364
365        Ok(return_data)
366    }
367
368    pub fn fold_bytes(bytes: &[Vec<u8>]) -> Vec<u8> {
369        bytes.iter().fold(Vec::new(), |mut acc, byte| {
370            acc.extend(byte.clone());
371            acc
372        })
373    }
374
375    pub fn fold_index_result(bytes: &[IndexedDataResult]) -> Vec<u8> {
376        bytes.iter().fold(Vec::new(), |mut acc, index| {
377            acc.extend(index.data.clone());
378            acc
379        })
380    }
381
382    pub fn fold_index(bytes: &[IndexedData]) -> Vec<u8> {
383        bytes.iter().fold(Vec::new(), |mut acc, index| {
384            acc.extend(index.data.clone());
385            acc
386        })
387    }
388
389    pub fn get_differences(diff_bytes: &[u8]) -> BTreeMap<u8, EntryDifference> {
390        Self::on_get_differences(diff_bytes, true)
391    }
392
393    pub fn get_index_mapping(&self) -> BTreeMap<u8, HistoryValue> {
394        self.last_index_mapping.clone()
395    }
396
397    fn on_get_differences(diff_bytes: &[u8], has_crc: bool) -> BTreeMap<u8, EntryDifference> {
398        let diff_bytes = if has_crc {
399            Self::get_differences_bytes_with_crc(diff_bytes)
400        } else {
401            diff_bytes
402        };
403        let mut diffs: BTreeMap<u8, EntryDifference> = BTreeMap::new();
404        let mut i = 0;
405        let mut index = 0;
406        while i < diff_bytes.len() {
407            // get index
408            if diff_bytes[i] == b'v' {
409                index = diff_bytes[i + 1];
410                i += 2;
411            }
412            // handle remove entry
413            if diff_bytes[i] == b'r' {
414                i += 1;
415                diffs.insert(index, EntryDifference::remove_entry());
416                continue;
417            }
418            // handle map name changes
419            if diff_bytes[i] == b'm' {
420                i += 1;
421                let map_diffs_length = Difference::get_usize_type_from_bytes(&diff_bytes[i..]);
422                i += map_diffs_length.1;
423                let bytes = &diff_bytes[i..(i + map_diffs_length.0)];
424                i += bytes.len();
425
426                // get the diffs for the map name
427                let map_diffs_result = Self::on_get_differences(bytes, false);
428                let map_entry_diff = map_diffs_result.get(&0);
429                if map_entry_diff.is_none() {
430                    continue;
431                }
432                let map_entry_diff = map_entry_diff.unwrap().to_owned().diffs.clone();
433
434                // insert the map name changed diff
435                if let Some(d) = diffs.get_mut(&index) {
436                    d.map_name_changed = Some(map_entry_diff);
437                } else {
438                    diffs.insert(index, EntryDifference::new(Vec::new()));
439                    diffs.get_mut(&index).unwrap().map_name_changed = Some(map_entry_diff);
440                }
441
442                continue;
443            }
444
445            let diff_length = Difference::get_usize_type_from_bytes(&diff_bytes[i..]);
446            i += diff_length.1;
447            let bytes = &diff_bytes[i..(i + diff_length.0)];
448            let diff = Difference::from_bytes(bytes);
449            i += diff_length.0;
450
451            if let Some(d) = diffs.get_mut(&index) {
452                d.diffs.push(diff);
453            } else {
454                diffs.insert(index, EntryDifference::new(vec![diff]));
455            }
456        }
457        diffs
458    }
459
460    pub fn get_differences_bytes_with_crc(diff_bytes: &[u8]) -> &[u8] {
461        let crc_length = diff_bytes[0];
462        let _crc_value = &diff_bytes[1..(1 + crc_length as usize)];
463        &diff_bytes[(1 + crc_length as usize)..]
464    }
465
466    fn fold_indexed_data(data: &[IndexedData]) -> Vec<u8> {
467        data.iter().fold(Vec::new(), |mut acc, indexed_data| {
468            acc.extend(indexed_data.data.clone());
469            acc
470        })
471    }
472
473    fn get_sorted(data: &[IndexedData]) -> Vec<IndexedData> {
474        let mut data = data.to_vec();
475        data.sort_by(|a, b| a.index.cmp(&b.index));
476        data
477    }
478}