Skip to main content

webrender/prim_store/
storage.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use std::{ops, marker::PhantomData, u32};
6use crate::util::Recycler;
7
8#[derive(Debug, Hash)]
9#[cfg_attr(feature = "capture", derive(Serialize))]
10#[cfg_attr(feature = "replay", derive(Deserialize))]
11pub struct Index<T>(pub u32, PhantomData<T>);
12
13impl<T> Index<T> {
14    /// Construct an Index from a raw u32. Caller is responsible for the
15    /// value matching the underlying storage.
16    pub fn from_u32(idx: u32) -> Self {
17        Index(idx, PhantomData)
18    }
19}
20
21// We explicitly implement Copy + Clone instead of using #[derive(Copy, Clone)]
22// because we don't want to require that T implements Clone + Copy.
23impl<T> Clone for Index<T> {
24    fn clone(&self) -> Self { *self }
25}
26
27impl<T> Copy for Index<T> {}
28
29impl<T> PartialEq for Index<T> {
30    fn eq(&self, other: &Self) -> bool {
31        self.0 == other.0
32    }
33}
34
35impl<T> Index<T> {
36    fn new(idx: usize) -> Self {
37        debug_assert!(idx < u32::max_value() as usize);
38        Index(idx as u32, PhantomData)
39    }
40
41    pub const INVALID: Index<T> = Index(u32::MAX, PhantomData);
42    pub const UNUSED: Index<T> = Index(u32::MAX-1, PhantomData);
43}
44
45#[derive(Debug)]
46pub struct OpenRange<T> {
47    start: Index<T>,
48}
49
50#[derive(Debug)]
51#[cfg_attr(feature = "capture", derive(Serialize))]
52pub struct Range<T> {
53    pub start: Index<T>,
54    pub end: Index<T>,
55}
56
57// We explicitly implement Copy + Clone instead of using #[derive(Copy, Clone)]
58// because we don't want to require that T implements Clone + Copy.
59impl<T> Clone for Range<T> {
60    fn clone(&self) -> Self {
61        Range { start: self.start, end: self.end }
62    }
63}
64impl<T> Copy for Range<T> {}
65
66impl<T> Range<T> {
67    /// Create an empty `Range`
68    pub fn empty() -> Self {
69        Range {
70            start: Index::new(0),
71            end: Index::new(0),
72        }
73    }
74
75    /// Check for an empty `Range`
76    pub fn is_empty(self) -> bool {
77        self.start.0 >= self.end.0
78    }
79}
80
81#[cfg_attr(feature = "capture", derive(Serialize))]
82pub struct Storage<T> {
83    data: Vec<T>,
84    /// Debug-only count of currently open ranges. Incremented by
85    /// `open_range`, decremented by `close_range`. `clear`/`recycle`
86    /// assert this is zero so a forgotten `close_range` is caught at
87    /// frame reset rather than silently producing wrong ranges later.
88    #[cfg(debug_assertions)]
89    open_count: u32,
90}
91
92impl<T> Storage<T> {
93    pub fn new(initial_capacity: usize) -> Self {
94        Storage {
95            data: Vec::with_capacity(initial_capacity),
96            #[cfg(debug_assertions)]
97            open_count: 0,
98        }
99    }
100
101    pub fn len(&self) -> usize {
102        self.data.len()
103    }
104
105    pub fn clear(&mut self) {
106        #[cfg(debug_assertions)]
107        debug_assert_eq!(
108            self.open_count, 0,
109            "Storage::clear with {} open range(s) — open_range without close_range",
110            self.open_count,
111        );
112        self.data.clear();
113    }
114
115    pub fn push(&mut self, t: T) -> Index<T> {
116        let index = self.data.len();
117        self.data.push(t);
118        Index(index as u32, PhantomData)
119    }
120
121    pub fn reserve(&mut self, count: usize) {
122        self.data.reserve(count);
123    }
124
125    pub fn recycle(&mut self, recycler: &mut Recycler) {
126        #[cfg(debug_assertions)]
127        debug_assert_eq!(
128            self.open_count, 0,
129            "Storage::recycle with {} open range(s) — open_range without close_range",
130            self.open_count,
131        );
132        recycler.recycle_vec(&mut self.data);
133    }
134
135    pub fn extend<II: IntoIterator<Item=T>>(&mut self, iter: II) -> Range<T> {
136        let range = self.open_range();
137        self.data.extend(iter);
138
139        self.close_range(range)
140    }
141
142    /// Direct `&mut Vec<T>` access to the backing storage, for builders
143    /// that push into multiple arenas in interleaved fashion and need to
144    /// hold split borrows on the underlying `Vec`s simultaneously.
145    /// Callers must only append; mutating or removing existing entries
146    /// invalidates previously-issued `Index`/`Range` handles. Pair with
147    /// `open_range`/`close_range` to capture the appended span.
148    pub fn data_mut(&mut self) -> &mut Vec<T> {
149        &mut self.data
150    }
151
152    pub fn open_range(&mut self) -> OpenRange<T> {
153        #[cfg(debug_assertions)]
154        {
155            self.open_count += 1;
156        }
157        OpenRange {
158            start: Index::new(self.data.len())
159        }
160    }
161
162    pub fn close_range(&mut self, range: OpenRange<T>) -> Range<T> {
163        #[cfg(debug_assertions)]
164        {
165            debug_assert!(
166                self.open_count > 0,
167                "Storage::close_range with no matching open_range",
168            );
169            self.open_count -= 1;
170        }
171        Range {
172            start: range.start,
173            end: Index::new(self.data.len()),
174        }
175    }
176}
177
178impl<T> ops::Index<Index<T>> for Storage<T> {
179    type Output = T;
180    fn index(&self, index: Index<T>) -> &Self::Output {
181        &self.data[index.0 as usize]
182    }
183}
184
185impl<T> ops::IndexMut<Index<T>> for Storage<T> {
186    fn index_mut(&mut self, index: Index<T>) -> &mut Self::Output {
187        &mut self.data[index.0 as usize]
188    }
189}
190
191impl<T> ops::Index<Range<T>> for Storage<T> {
192    type Output = [T];
193    fn index(&self, index: Range<T>) -> &Self::Output {
194        let start = index.start.0 as _;
195        let end = index.end.0 as _;
196        &self.data[start..end]
197    }
198}
199
200impl<T> ops::IndexMut<Range<T>> for Storage<T> {
201    fn index_mut(&mut self, index: Range<T>) -> &mut Self::Output {
202        let start = index.start.0 as _;
203        let end = index.end.0 as _;
204        &mut self.data[start..end]
205    }
206}