style/stylesheets/
origin.rs1use std::marker::PhantomData;
8use std::ops::BitOrAssign;
9
10#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem, PartialOrd, Ord)]
14#[repr(u8)]
15pub enum Origin {
16 UserAgent = 0x1,
18
19 User = 0x2,
21
22 Author = 0x4,
24}
25
26impl Origin {
27 fn from_index(index: i8) -> Option<Self> {
31 Some(match index {
32 0 => Origin::Author,
33 1 => Origin::User,
34 2 => Origin::UserAgent,
35 _ => return None,
36 })
37 }
38
39 fn to_index(self) -> i8 {
40 match self {
41 Origin::Author => 0,
42 Origin::User => 1,
43 Origin::UserAgent => 2,
44 }
45 }
46
47 #[inline]
50 pub fn following_including(self) -> OriginSetIterator {
51 OriginSetIterator {
52 set: OriginSet::ORIGIN_USER | OriginSet::ORIGIN_AUTHOR | OriginSet::ORIGIN_USER_AGENT,
53 cur: self.to_index(),
54 rev: true,
55 }
56 }
57}
58
59#[derive(Clone, Copy, PartialEq, MallocSizeOf)]
61pub struct OriginSet(u8);
62bitflags! {
63 impl OriginSet: u8 {
64 const ORIGIN_USER_AGENT = Origin::UserAgent as u8;
66 const ORIGIN_USER = Origin::User as u8;
68 const ORIGIN_AUTHOR = Origin::Author as u8;
70 }
71}
72
73impl OriginSet {
74 pub fn iter_origins(&self) -> OriginSetIterator {
79 OriginSetIterator {
80 set: *self,
81 cur: 0,
82 rev: false,
83 }
84 }
85}
86
87impl From<Origin> for OriginSet {
88 fn from(origin: Origin) -> Self {
89 Self::from_bits_retain(origin as u8)
90 }
91}
92
93impl BitOrAssign<Origin> for OriginSet {
94 fn bitor_assign(&mut self, origin: Origin) {
95 *self |= OriginSet::from(origin);
96 }
97}
98
99#[derive(Clone)]
102pub struct OriginSetIterator {
103 set: OriginSet,
104 cur: i8,
105 rev: bool,
106}
107
108impl Iterator for OriginSetIterator {
109 type Item = Origin;
110
111 fn next(&mut self) -> Option<Origin> {
112 loop {
113 let origin = Origin::from_index(self.cur)?;
114
115 if self.rev {
116 self.cur -= 1;
117 } else {
118 self.cur += 1;
119 }
120
121 if self.set.contains(origin.into()) {
122 return Some(origin);
123 }
124 }
125 }
126}
127
128#[derive(Debug, Default, MallocSizeOf)]
130pub struct PerOrigin<T> {
131 pub user_agent: T,
133
134 pub user: T,
136
137 pub author: T,
139}
140
141impl<T> PerOrigin<T> {
142 #[inline]
144 pub fn borrow_for_origin(&self, origin: &Origin) -> &T {
145 match *origin {
146 Origin::UserAgent => &self.user_agent,
147 Origin::User => &self.user,
148 Origin::Author => &self.author,
149 }
150 }
151
152 #[inline]
155 pub fn borrow_mut_for_origin(&mut self, origin: &Origin) -> &mut T {
156 match *origin {
157 Origin::UserAgent => &mut self.user_agent,
158 Origin::User => &mut self.user,
159 Origin::Author => &mut self.author,
160 }
161 }
162
163 pub fn iter_origins(&self) -> PerOriginIter<T> {
166 PerOriginIter {
167 data: &self,
168 cur: 0,
169 rev: false,
170 }
171 }
172
173 pub fn iter_origins_rev(&self) -> PerOriginIter<T> {
176 PerOriginIter {
177 data: &self,
178 cur: 2,
179 rev: true,
180 }
181 }
182
183 pub fn iter_mut_origins(&mut self) -> PerOriginIterMut<T> {
186 PerOriginIterMut {
187 data: self,
188 cur: 0,
189 _marker: PhantomData,
190 }
191 }
192}
193
194pub struct PerOriginIter<'a, T: 'a> {
200 data: &'a PerOrigin<T>,
201 cur: i8,
202 rev: bool,
203}
204
205impl<'a, T> Iterator for PerOriginIter<'a, T>
206where
207 T: 'a,
208{
209 type Item = (&'a T, Origin);
210
211 fn next(&mut self) -> Option<Self::Item> {
212 let origin = Origin::from_index(self.cur)?;
213
214 self.cur += if self.rev { -1 } else { 1 };
215
216 Some((self.data.borrow_for_origin(&origin), origin))
217 }
218}
219
220pub struct PerOriginIterMut<'a, T: 'a> {
227 data: *mut PerOrigin<T>,
228 cur: i8,
229 _marker: PhantomData<&'a mut PerOrigin<T>>,
230}
231
232impl<'a, T> Iterator for PerOriginIterMut<'a, T>
233where
234 T: 'a,
235{
236 type Item = (&'a mut T, Origin);
237
238 fn next(&mut self) -> Option<Self::Item> {
239 let origin = Origin::from_index(self.cur)?;
240
241 self.cur += 1;
242
243 Some((
244 unsafe { (*self.data).borrow_mut_for_origin(&origin) },
245 origin,
246 ))
247 }
248}