1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use serde_json::{Map, Value};
use fnv::FnvHashMap;

use super::{Order, Patch, RawView};

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Transaction {
    events: FnvHashMap<String, FnvHashMap<String, bool>>,
    removes: FnvHashMap<String, RawView>,
    patches: FnvHashMap<String, Vec<Patch>>,
}

impl Transaction {
    #[inline(always)]
    pub fn new() -> Self {
        Transaction {
            events: FnvHashMap::default(),
            removes: FnvHashMap::default(),
            patches: FnvHashMap::default(),
        }
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.events.is_empty() && self.removes.is_empty() && self.patches.is_empty()
    }

    #[inline]
    pub fn mount(&mut self, id: &str, view: RawView) {
        self.append(id.into(), Patch::Mount(view));
    }
    #[inline]
    pub fn unmount(&mut self, id: &str, view: RawView) {
        self.removes.insert(id.into(), view);
    }

    #[inline]
    pub fn insert(&mut self, id: &str, view_id: &str, index: usize, view: RawView) {
        self.append(id.into(), Patch::Insert(view_id.into(), index, view));
    }
    #[inline]
    pub fn replace(&mut self, id: &str, prev_view: RawView, next_view: RawView) {
        self.append(id.into(), Patch::Replace(prev_view, next_view));
    }
    #[inline]
    pub fn order(&mut self, id: &str, order: Order) {
        self.append(id.into(), Patch::Order(order));
    }
    #[inline]
    pub fn props(
        &mut self,
        id: &str,
        prev_props: Map<String, Value>,
        diff_props: Map<String, Value>,
    ) {
        self.append(id.into(), Patch::Props(prev_props, diff_props));
    }

    #[inline]
    pub fn remove(&mut self, id: &str, view: RawView) {
        self.removes.insert(id.into(), view);
    }

    #[inline]
    pub fn add_event(&mut self, id: &str, name: &str) {
        self.append_event(id.into(), name.into(), true);
    }
    #[inline]
    pub fn remove_event(&mut self, id: &str, name: &str) {
        self.append_event(id.into(), name.into(), false);
    }

    #[inline(always)]
    pub fn events(&self) -> &FnvHashMap<String, FnvHashMap<String, bool>> {
        &self.events
    }
    #[inline(always)]
    pub fn removes(&self) -> &FnvHashMap<String, RawView> {
        &self.removes
    }
    #[inline(always)]
    pub fn patches(&self) -> &FnvHashMap<String, Vec<Patch>> {
        &self.patches
    }

    #[inline]
    fn append(&mut self, id: String, patch: Patch) {
        if !self.patches.contains_key(&id) {
            self.patches.insert(id.clone(), Vec::new());
        }

        let array = self.patches.get_mut(&id).unwrap();
        array.push(patch);
    }

    #[inline]
    fn append_event(&mut self, id: String, name: String, value: bool) {
        if !self.events.contains_key(&id) {
            self.events.insert(id.clone(), FnvHashMap::default());
        }

        let map = self.events.get_mut(&id).unwrap();
        map.insert(name, value);
    }
}