Skip to main content

trellis_core/
scope_lifecycle.rs

1use crate::{Graph, GraphResult, ResourceKey, ScopeId};
2
3impl<C, O> Graph<C, O> {
4    pub(crate) fn close_scope_direct(&mut self, scope: ScopeId) -> GraphResult<Vec<ScopeId>> {
5        self.require_scope(scope)?;
6        let scopes = self.scope_close_order(scope);
7        for closing in &scopes {
8            if let Some(scope_meta) = self.scopes.get_mut(closing) {
9                scope_meta.close();
10            }
11            self.resource_planners
12                .retain(|planner| planner.scope != *closing);
13            for node in self.nodes.values_mut() {
14                node.detach_scope(*closing);
15            }
16        }
17        Ok(scopes)
18    }
19
20    /// Returns child scopes in stable id order.
21    pub fn child_scopes(&self, scope: ScopeId) -> GraphResult<Vec<ScopeId>> {
22        self.require_scope(scope)?;
23        Ok(self.child_scopes_unchecked(scope))
24    }
25
26    /// Returns resources whose owner set is empty or contains no live scope.
27    pub fn orphan_resources(&self) -> Vec<ResourceKey> {
28        self.resource_owners
29            .iter()
30            .filter_map(|(key, owners)| {
31                let has_live_owner = owners
32                    .iter()
33                    .any(|scope| self.scopes.get(scope).is_some_and(|meta| !meta.is_closed()));
34                (!has_live_owner).then(|| key.clone())
35            })
36            .collect()
37    }
38
39    fn scope_close_order(&self, scope: ScopeId) -> Vec<ScopeId> {
40        let mut scopes = Vec::new();
41        self.collect_scope_close_order(scope, &mut scopes);
42        scopes
43    }
44
45    fn collect_scope_close_order(&self, scope: ScopeId, scopes: &mut Vec<ScopeId>) {
46        for child in self.child_scopes_unchecked(scope) {
47            self.collect_scope_close_order(child, scopes);
48        }
49        if self
50            .scopes
51            .get(&scope)
52            .is_some_and(|scope_meta| !scope_meta.is_closed())
53        {
54            scopes.push(scope);
55        }
56    }
57
58    fn child_scopes_unchecked(&self, scope: ScopeId) -> Vec<ScopeId> {
59        self.scopes
60            .values()
61            .filter_map(|scope_meta| {
62                (scope_meta.parent() == Some(scope)).then_some(scope_meta.id())
63            })
64            .collect()
65    }
66}