webrender/
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::{iter::Extend, 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>(u32, PhantomData<T>);
12
13// We explicitly implement Copy + Clone instead of using #[derive(Copy, Clone)]
14// because we don't want to require that T implements Clone + Copy.
15impl<T> Clone for Index<T> {
16    fn clone(&self) -> Self { *self }
17}
18
19impl<T> Copy for Index<T> {}
20
21impl<T> PartialEq for Index<T> {
22    fn eq(&self, other: &Self) -> bool {
23        self.0 == other.0
24    }
25}
26
27impl<T> Index<T> {
28    fn new(idx: usize) -> Self {
29        debug_assert!(idx < u32::max_value() as usize);
30        Index(idx as u32, PhantomData)
31    }
32
33    pub const INVALID: Index<T> = Index(u32::MAX, PhantomData);
34    pub const UNUSED: Index<T> = Index(u32::MAX-1, PhantomData);
35}
36
37#[derive(Debug)]
38#[cfg_attr(feature = "capture", derive(Serialize))]
39pub struct Range<T> {
40    pub start: Index<T>,
41    pub end: Index<T>,
42}
43
44// We explicitly implement Copy + Clone instead of using #[derive(Copy, Clone)]
45// because we don't want to require that T implements Clone + Copy.
46impl<T> Clone for Range<T> {
47    fn clone(&self) -> Self {
48        Range { start: self.start, end: self.end }
49    }
50}
51impl<T> Copy for Range<T> {}
52
53impl<T> Range<T> {
54    /// Create an empty `Range`
55    pub fn empty() -> Self {
56        Range {
57            start: Index::new(0),
58            end: Index::new(0),
59        }
60    }
61
62    /// Check for an empty `Range`
63    pub fn is_empty(self) -> bool {
64        self.start.0 >= self.end.0
65    }
66}
67
68#[cfg_attr(feature = "capture", derive(Serialize))]
69pub struct Storage<T> {
70    data: Vec<T>,
71}
72
73impl<T> Storage<T> {
74    pub fn new(initial_capacity: usize) -> Self {
75        Storage {
76            data: Vec::with_capacity(initial_capacity),
77        }
78    }
79
80    pub fn len(&self) -> usize {
81        self.data.len()
82    }
83
84    pub fn clear(&mut self) {
85        self.data.clear();
86    }
87
88    pub fn push(&mut self, t: T) -> Index<T> {
89        let index = self.data.len();
90        self.data.push(t);
91        Index(index as u32, PhantomData)
92    }
93
94    pub fn recycle(&mut self, recycler: &mut Recycler) {
95        recycler.recycle_vec(&mut self.data);
96    }
97
98    pub fn extend<II: IntoIterator<Item=T>>(&mut self, iter: II) -> Range<T> {
99        let start = Index::new(self.data.len());
100        self.data.extend(iter);
101        let end = Index::new(self.data.len());
102        Range { start, end }
103    }
104}
105
106impl<T> ops::Index<Index<T>> for Storage<T> {
107    type Output = T;
108    fn index(&self, index: Index<T>) -> &Self::Output {
109        &self.data[index.0 as usize]
110    }
111}
112
113impl<T> ops::IndexMut<Index<T>> for Storage<T> {
114    fn index_mut(&mut self, index: Index<T>) -> &mut Self::Output {
115        &mut self.data[index.0 as usize]
116    }
117}
118
119impl<T> ops::Index<Range<T>> for Storage<T> {
120    type Output = [T];
121    fn index(&self, index: Range<T>) -> &Self::Output {
122        let start = index.start.0 as _;
123        let end = index.end.0 as _;
124        &self.data[start..end]
125    }
126}
127
128impl<T> ops::IndexMut<Range<T>> for Storage<T> {
129    fn index_mut(&mut self, index: Range<T>) -> &mut Self::Output {
130        let start = index.start.0 as _;
131        let end = index.end.0 as _;
132        &mut self.data[start..end]
133    }
134}