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