xvc_ecs/ecs/
r1nstore.rs

1//! Represents 1-N (parent-child) relationships.
2//! Each child has a one parent but each parent can have multiple children.
3use super::XvcEntity;
4use crate::error::{Error, Result};
5use crate::{HStore, Storable, XvcStore};
6use serde::{Deserialize, Serialize};
7use std::fmt::Debug;
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::path::Path;
11
12/// Wrapper around XvcEntity that represents a parent-child relationship.
13///
14/// The key for the XvcStore that keeps the relatinship is the child entity, as there are many
15/// children for a parent. XvcStore doesn't allow duplicate keys so XvcStore<ChildEntity<T, U>> is
16/// a 1-N relationship between T and U. There are many T (children) for a U (parent).
17#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
18pub struct ChildEntity<T: Storable, U: Storable>(XvcEntity, PhantomData<T>, PhantomData<U>);
19
20impl<T: Storable, U: Storable> Storable for ChildEntity<T, U> {
21    fn type_description() -> String {
22        format!(
23            "{}-{}-r1n",
24            <T as Storable>::type_description(),
25            <U as Storable>::type_description()
26        )
27    }
28}
29
30impl<T: Storable, U: Storable> From<XvcEntity> for ChildEntity<T, U> {
31    fn from(xe: XvcEntity) -> Self {
32        Self(xe, PhantomData, PhantomData)
33    }
34}
35
36impl<T: Storable, U: Storable> From<ChildEntity<T, U>> for XvcEntity {
37    fn from(r1ne: ChildEntity<T, U>) -> Self {
38        r1ne.0
39    }
40}
41
42impl<T: Storable, U: Storable> Deref for ChildEntity<T, U> {
43    type Target = XvcEntity;
44
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49
50/// RNStore is 1-N RelationStore, where we store one-to-many relationships between two entities.
51/// It doesn't have any semantics except binding two entities together.
52#[derive(Debug, Clone)]
53pub struct R1NStore<T, U>
54where
55    T: Storable,
56    U: Storable,
57{
58    /// Keeps the parent type
59    pub parents: XvcStore<T>,
60    /// Keeps the child type
61    pub children: XvcStore<U>,
62    /// Keeps the relationships between child entities and parent entities
63    /// The key for the child_parents is the child entity, as there are many children for a parent.
64    pub child_parents: XvcStore<ChildEntity<U, T>>,
65}
66
67impl<T, U> R1NStore<T, U>
68where
69    T: Storable,
70    U: Storable,
71{
72    /// Insert a child component to a parent parent_component.
73    /// It checks whether the parent is equal to the given, and updates if there is a change.
74    pub fn insert(
75        &mut self,
76        parent_entity: XvcEntity,
77        parent_component: T,
78        child_entity: XvcEntity,
79        child_component: U,
80    ) -> Option<XvcEntity> {
81        match self.parents.get(&parent_entity) {
82            None => {
83                self.parents.insert(parent_entity, parent_component);
84            }
85            Some(value) => {
86                if *value != parent_component {
87                    self.parents.update(parent_entity, parent_component);
88                }
89            }
90        }
91
92        self.children.insert(child_entity, child_component);
93        // CAUTION: The order is reversed!
94        self.child_parents
95            .insert(child_entity, parent_entity.into())
96            .map(XvcEntity::from)
97    }
98
99    /// get the store of related entities.
100    pub fn children_of(&self, parent_entity: &XvcEntity) -> Result<HStore<U>> {
101        let related_entities = self.child_parents.iter().filter_map(|(child, parent)| {
102            if *parent == (*parent_entity).into() {
103                Some(*child)
104            } else {
105                None
106            }
107        });
108        self.children.subset(related_entities)
109    }
110
111    /// Get left entity that's related with thethe right `child_entity`.
112    pub fn parent_of(&self, child_entity: &XvcEntity) -> Result<(&ChildEntity<U, T>, &T)> {
113        match self.child_parents.get(child_entity) {
114            None => Err(Error::NoParentEntityFound {
115                entity: (*child_entity),
116            }),
117            Some(p_e) => {
118                let (_, v) = self
119                    .parents
120                    .get_key_value(p_e)
121                    .ok_or(Error::NoParentEntityFound {
122                        entity: *child_entity,
123                    })?;
124                Ok((p_e, v))
125            }
126        }
127    }
128
129    /// Remove the child entity from child-parent store and children store
130    pub fn remove_child(&mut self, child_entity: XvcEntity) -> Result<()> {
131        self.child_parents.remove(child_entity);
132        self.children.remove(child_entity);
133        Ok(())
134    }
135}
136
137impl<T, U> R1NStore<T, U>
138where
139    T: Storable,
140    U: Storable,
141{
142    /// Loads the stores from store root and directory named after type names
143    pub fn load_r1nstore(store_root: &Path) -> Result<R1NStore<T, U>> {
144        let parents = XvcStore::<T>::load_store(store_root)?;
145        let children = XvcStore::<U>::load_store(store_root)?;
146        let child_parents = XvcStore::<ChildEntity<U, T>>::load_store(store_root)?;
147
148        Ok(R1NStore {
149            parents,
150            children,
151            child_parents,
152        })
153    }
154
155    /// Records the stores to store root and directories created from type names
156    pub fn save_r1nstore(store: &Self, store_root: &Path) -> Result<()> {
157        store.parents.save(store_root)?;
158        store.children.save(store_root)?;
159        store.child_parents.save(store_root)
160    }
161}