es_entity/
nested.rs

1//! Handle operations for nested entities.
2
3use crate::{operation::AtomicOperation, traits::*};
4
5use std::collections::HashMap;
6
7pub struct Nested<T: EsEntity> {
8    entities: HashMap<<<T as EsEntity>::Event as EsEvent>::EntityId, T>,
9    new_entities: Vec<<T as EsEntity>::New>,
10}
11
12impl<T: EsEntity> Default for Nested<T> {
13    fn default() -> Self {
14        Self {
15            entities: HashMap::new(),
16            new_entities: Vec::new(),
17        }
18    }
19}
20
21impl<T: EsEntity> Nested<T> {
22    pub fn add_new(&mut self, new: <T as EsEntity>::New) -> &<T as EsEntity>::New {
23        let len = self.new_entities.len();
24        self.new_entities.push(new);
25        &self.new_entities[len]
26    }
27
28    pub fn get_persisted(&self, id: &<<T as EsEntity>::Event as EsEvent>::EntityId) -> Option<&T> {
29        self.entities.get(id)
30    }
31
32    pub fn get_persisted_mut(
33        &mut self,
34        id: &<<T as EsEntity>::Event as EsEvent>::EntityId,
35    ) -> Option<&mut T> {
36        self.entities.get_mut(id)
37    }
38
39    pub fn find_persisted<P>(&self, predicate: P) -> Option<&T>
40    where
41        P: FnMut(&&T) -> bool,
42    {
43        self.entities.values().find(predicate)
44    }
45
46    pub fn find_map_persisted<B, F>(&self, f: F) -> Option<B>
47    where
48        F: FnMut(&T) -> Option<B>,
49    {
50        self.entities.values().find_map(f)
51    }
52
53    pub fn find_persisted_mut<P>(&mut self, predicate: P) -> Option<&mut T>
54    where
55        P: FnMut(&&mut T) -> bool,
56    {
57        self.entities.values_mut().find(predicate)
58    }
59
60    pub fn len_persisted(&self) -> usize {
61        self.entities.len()
62    }
63
64    pub fn iter_persisted(
65        &self,
66    ) -> std::collections::hash_map::Values<'_, <<T as EsEntity>::Event as EsEvent>::EntityId, T>
67    {
68        self.entities.values()
69    }
70
71    pub fn iter_persisted_mut(
72        &mut self,
73    ) -> std::collections::hash_map::ValuesMut<'_, <<T as EsEntity>::Event as EsEvent>::EntityId, T>
74    {
75        self.entities.values_mut()
76    }
77
78    pub fn find_new<P>(&self, predicate: P) -> Option<&<T as EsEntity>::New>
79    where
80        P: FnMut(&&<T as EsEntity>::New) -> bool,
81    {
82        self.new_entities.iter().find(predicate)
83    }
84
85    pub fn find_map_new<B, F>(&self, f: F) -> Option<B>
86    where
87        F: FnMut(&<T as EsEntity>::New) -> Option<B>,
88    {
89        self.new_entities.iter().find_map(f)
90    }
91
92    pub fn new_entities_mut(&mut self) -> &mut Vec<<T as EsEntity>::New> {
93        &mut self.new_entities
94    }
95
96    pub fn load(&mut self, entities: impl IntoIterator<Item = T>) {
97        self.entities.extend(
98            entities
99                .into_iter()
100                .map(|entity| (entity.events().entity_id.clone(), entity)),
101        );
102    }
103}
104
105pub trait PopulateNested<ID>: EsRepo {
106    fn populate_in_op<OP, P>(
107        op: &mut OP,
108        lookup: std::collections::HashMap<ID, &mut P>,
109    ) -> impl Future<Output = Result<(), <Self as EsRepo>::Err>> + Send
110    where
111        OP: AtomicOperation,
112        P: Parent<<Self as EsRepo>::Entity>;
113}
114
115/// Trait that entities implement for every field marked `#[es_entity(nested)]`
116///
117/// Will be auto-implemented when [`#[derive(EsEntity)]`](`EsEntity`) is used.
118pub trait Parent<T: EsEntity>: Send {
119    /// Access new child entities to persist them.
120    fn new_children_mut(&mut self) -> &mut Vec<<T as EsEntity>::New>;
121    /// Access existing children to update them incase they were mutated.
122    fn iter_persisted_children_mut(
123        &mut self,
124    ) -> std::collections::hash_map::ValuesMut<'_, <<T as EsEntity>::Event as EsEvent>::EntityId, T>;
125    /// Inject hydrated children while loading the parent.
126    fn inject_children(&mut self, entities: impl IntoIterator<Item = T>);
127}