1use crate::{Graph, GraphResult, NodeId, ScopeId};
2use core::fmt;
3use std::sync::Arc;
4
5#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
7pub struct ResourceKey(Box<str>);
8
9impl ResourceKey {
10 pub fn new(key: impl Into<Box<str>>) -> Self {
12 Self(key.into())
13 }
14
15 pub fn as_str(&self) -> &str {
17 &self.0
18 }
19}
20
21impl fmt::Debug for ResourceKey {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 f.debug_tuple("ResourceKey").field(&self.0).finish()
24 }
25}
26
27#[derive(Clone, Debug, Eq, PartialEq)]
29pub enum ResourceCommand<C> {
30 Open {
32 key: ResourceKey,
34 scope: ScopeId,
36 command: C,
38 },
39 Close {
41 key: ResourceKey,
43 scope: ScopeId,
45 },
46 Replace {
48 key: ResourceKey,
50 scope: ScopeId,
52 command: C,
54 },
55 Refresh {
57 key: ResourceKey,
59 scope: ScopeId,
61 command: C,
63 },
64}
65
66impl<C> ResourceCommand<C> {
67 pub fn key(&self) -> &ResourceKey {
69 match self {
70 Self::Open { key, .. }
71 | Self::Close { key, .. }
72 | Self::Replace { key, .. }
73 | Self::Refresh { key, .. } => key,
74 }
75 }
76
77 pub fn scope(&self) -> ScopeId {
79 match self {
80 Self::Open { scope, .. }
81 | Self::Close { scope, .. }
82 | Self::Replace { scope, .. }
83 | Self::Refresh { scope, .. } => *scope,
84 }
85 }
86}
87
88#[derive(Clone, Debug, Eq, PartialEq)]
90pub struct ResourcePlan<C> {
91 commands: Vec<ResourceCommand<C>>,
92}
93
94impl<C> ResourcePlan<C> {
95 pub fn new() -> Self {
97 Self {
98 commands: Vec::new(),
99 }
100 }
101
102 pub fn open(&mut self, key: ResourceKey, scope: ScopeId, command: C) {
104 self.commands.push(ResourceCommand::Open {
105 key,
106 scope,
107 command,
108 });
109 }
110
111 pub fn close(&mut self, key: ResourceKey, scope: ScopeId) {
113 self.commands.push(ResourceCommand::Close { key, scope });
114 }
115
116 pub fn replace(&mut self, key: ResourceKey, scope: ScopeId, command: C) {
118 self.commands.push(ResourceCommand::Replace {
119 key,
120 scope,
121 command,
122 });
123 }
124
125 pub fn refresh(&mut self, key: ResourceKey, scope: ScopeId, command: C) {
127 self.commands.push(ResourceCommand::Refresh {
128 key,
129 scope,
130 command,
131 });
132 }
133
134 pub fn commands(&self) -> &[ResourceCommand<C>] {
136 &self.commands
137 }
138
139 pub fn into_commands(self) -> Vec<ResourceCommand<C>> {
141 self.commands
142 }
143
144 pub(crate) fn append(&mut self, other: ResourcePlan<C>) {
145 self.commands.extend(other.commands);
146 }
147}
148
149impl<C> Default for ResourcePlan<C> {
150 fn default() -> Self {
151 Self::new()
152 }
153}
154
155pub struct PlanContext<'graph, D> {
157 scope: ScopeId,
158 diff: &'graph D,
159}
160
161impl<'graph, D> PlanContext<'graph, D> {
162 pub(crate) fn new(scope: ScopeId, diff: &'graph D) -> Self {
163 Self { scope, diff }
164 }
165
166 pub fn scope(&self) -> ScopeId {
168 self.scope
169 }
170
171 pub fn diff(&self) -> &'graph D {
173 self.diff
174 }
175}
176
177type PlannerFn<C, O> = dyn Fn(&Graph<C, O>) -> GraphResult<ResourcePlan<C>>;
178
179pub(crate) struct ResourcePlanner<C, O> {
180 pub(crate) collection: NodeId,
181 pub(crate) scope: ScopeId,
182 run: Arc<PlannerFn<C, O>>,
183}
184
185impl<C, O> Clone for ResourcePlanner<C, O> {
186 fn clone(&self) -> Self {
187 Self {
188 collection: self.collection,
189 scope: self.scope,
190 run: Arc::clone(&self.run),
191 }
192 }
193}
194
195impl<C, O> ResourcePlanner<C, O> {
196 pub(crate) fn new(
197 collection: NodeId,
198 scope: ScopeId,
199 run: impl Fn(&Graph<C, O>) -> GraphResult<ResourcePlan<C>> + 'static,
200 ) -> Self {
201 Self {
202 collection,
203 scope,
204 run: Arc::new(run),
205 }
206 }
207
208 pub(crate) fn run(&self, graph: &Graph<C, O>) -> GraphResult<ResourcePlan<C>> {
209 (self.run)(graph)
210 }
211}