1use std::ops;
2use std::sync::Arc;
3
4use wgt::Backend;
5
6use crate::id::Id;
7use crate::resource::Resource;
8use crate::{Epoch, Index};
9
10#[derive(Debug)]
12pub(crate) enum Element<T> {
13 Vacant,
15
16 Occupied(Arc<T>, Epoch),
19
20 Error(Epoch, String),
25}
26
27#[derive(Clone, Debug)]
28pub(crate) struct InvalidId;
29
30#[derive(Debug)]
39pub(crate) struct Storage<T>
40where
41 T: Resource,
42{
43 pub(crate) map: Vec<Element<T>>,
44 kind: &'static str,
45}
46
47impl<T> ops::Index<Id<T::Marker>> for Storage<T>
48where
49 T: Resource,
50{
51 type Output = Arc<T>;
52 fn index(&self, id: Id<T::Marker>) -> &Arc<T> {
53 self.get(id).unwrap()
54 }
55}
56impl<T> Storage<T>
57where
58 T: Resource,
59{
60 pub(crate) fn new() -> Self {
61 Self {
62 map: Vec::new(),
63 kind: T::TYPE,
64 }
65 }
66}
67
68impl<T> Storage<T>
69where
70 T: Resource,
71{
72 #[allow(dead_code)]
73 pub(crate) fn contains(&self, id: Id<T::Marker>) -> bool {
74 let (index, epoch, _) = id.unzip();
75 match self.map.get(index as usize) {
76 Some(&Element::Vacant) => false,
77 Some(&Element::Occupied(_, storage_epoch) | &Element::Error(storage_epoch, _)) => {
78 storage_epoch == epoch
79 }
80 None => false,
81 }
82 }
83
84 pub(crate) fn try_get(&self, id: Id<T::Marker>) -> Result<Option<&Arc<T>>, InvalidId> {
92 let (index, epoch, _) = id.unzip();
93 let (result, storage_epoch) = match self.map.get(index as usize) {
94 Some(&Element::Occupied(ref v, epoch)) => (Ok(Some(v)), epoch),
95 Some(&Element::Vacant) => return Ok(None),
96 Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch),
97 None => return Err(InvalidId),
98 };
99 assert_eq!(
100 epoch, storage_epoch,
101 "{}[{:?}] is no longer alive",
102 self.kind, id
103 );
104 result
105 }
106
107 pub(crate) fn get(&self, id: Id<T::Marker>) -> Result<&Arc<T>, InvalidId> {
110 let (index, epoch, _) = id.unzip();
111 let (result, storage_epoch) = match self.map.get(index as usize) {
112 Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch),
113 Some(&Element::Vacant) => panic!("{}[{:?}] does not exist", self.kind, id),
114 Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch),
115 None => return Err(InvalidId),
116 };
117 assert_eq!(
118 epoch, storage_epoch,
119 "{}[{:?}] is no longer alive",
120 self.kind, id
121 );
122 result
123 }
124
125 pub(crate) fn get_owned(&self, id: Id<T::Marker>) -> Result<Arc<T>, InvalidId> {
128 Ok(Arc::clone(self.get(id)?))
129 }
130
131 pub(crate) fn label_for_invalid_id(&self, id: Id<T::Marker>) -> &str {
132 let (index, _, _) = id.unzip();
133 match self.map.get(index as usize) {
134 Some(Element::Error(_, label)) => label,
135 _ => "",
136 }
137 }
138
139 fn insert_impl(&mut self, index: usize, epoch: Epoch, element: Element<T>) {
140 if index >= self.map.len() {
141 self.map.resize_with(index + 1, || Element::Vacant);
142 }
143 match std::mem::replace(&mut self.map[index], element) {
144 Element::Vacant => {}
145 Element::Occupied(_, storage_epoch) => {
146 assert_ne!(
147 epoch,
148 storage_epoch,
149 "Index {index:?} of {} is already occupied",
150 T::TYPE
151 );
152 }
153 Element::Error(storage_epoch, _) => {
154 assert_ne!(
155 epoch,
156 storage_epoch,
157 "Index {index:?} of {} is already occupied with Error",
158 T::TYPE
159 );
160 }
161 }
162 }
163
164 pub(crate) fn insert(&mut self, id: Id<T::Marker>, value: Arc<T>) {
165 log::trace!("User is inserting {}{:?}", T::TYPE, id);
166 let (index, epoch, _backend) = id.unzip();
167 self.insert_impl(index as usize, epoch, Element::Occupied(value, epoch))
168 }
169
170 pub(crate) fn insert_error(&mut self, id: Id<T::Marker>, label: &str) {
171 log::trace!("User is inserting as error {}{:?}", T::TYPE, id);
172 let (index, epoch, _) = id.unzip();
173 self.insert_impl(
174 index as usize,
175 epoch,
176 Element::Error(epoch, label.to_string()),
177 )
178 }
179
180 pub(crate) fn replace_with_error(&mut self, id: Id<T::Marker>) -> Result<Arc<T>, InvalidId> {
181 let (index, epoch, _) = id.unzip();
182 match std::mem::replace(
183 &mut self.map[index as usize],
184 Element::Error(epoch, String::new()),
185 ) {
186 Element::Vacant => panic!("Cannot access vacant resource"),
187 Element::Occupied(value, storage_epoch) => {
188 assert_eq!(epoch, storage_epoch);
189 Ok(value)
190 }
191 _ => Err(InvalidId),
192 }
193 }
194
195 pub(crate) fn force_replace(&mut self, id: Id<T::Marker>, value: T) {
196 log::trace!("User is replacing {}{:?}", T::TYPE, id);
197 let (index, epoch, _) = id.unzip();
198 self.map[index as usize] = Element::Occupied(Arc::new(value), epoch);
199 }
200
201 pub(crate) fn remove(&mut self, id: Id<T::Marker>) -> Option<Arc<T>> {
202 log::trace!("User is removing {}{:?}", T::TYPE, id);
203 let (index, epoch, _) = id.unzip();
204 match std::mem::replace(&mut self.map[index as usize], Element::Vacant) {
205 Element::Occupied(value, storage_epoch) => {
206 assert_eq!(epoch, storage_epoch);
207 Some(value)
208 }
209 Element::Error(..) => None,
210 Element::Vacant => panic!("Cannot remove a vacant resource"),
211 }
212 }
213
214 pub(crate) fn iter(&self, backend: Backend) -> impl Iterator<Item = (Id<T::Marker>, &Arc<T>)> {
215 self.map
216 .iter()
217 .enumerate()
218 .filter_map(move |(index, x)| match *x {
219 Element::Occupied(ref value, storage_epoch) => {
220 Some((Id::zip(index as Index, storage_epoch, backend), value))
221 }
222 _ => None,
223 })
224 }
225
226 pub(crate) fn kind(&self) -> &str {
227 self.kind
228 }
229
230 pub(crate) fn len(&self) -> usize {
231 self.map.len()
232 }
233}