style/stylesheets/
layer_rule.rs1use crate::derives::*;
10use crate::parser::{Parse, ParserContext};
11use crate::shared_lock::{DeepCloneWithLock, Locked};
12use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
13use crate::values::AtomIdent;
14
15use super::CssRules;
16
17use cssparser::{Parser, SourceLocation, Token};
18use servo_arc::Arc;
19use smallvec::SmallVec;
20use std::fmt::{self, Write};
21use style_traits::{CssWriter, ParseError, ToCss};
22
23#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord)]
27pub struct LayerOrder(u16);
28
29impl LayerOrder {
30 pub const fn root() -> Self {
32 Self(std::u16::MAX - 1)
33 }
34
35 pub const fn style_attribute() -> Self {
37 Self(std::u16::MAX)
38 }
39
40 #[inline]
47 pub fn is_style_attribute_layer(&self) -> bool {
48 *self == Self::style_attribute()
49 }
50
51 pub const fn first() -> Self {
53 Self(0)
54 }
55
56 #[inline]
58 pub fn inc(&mut self) {
59 if self.0 != std::u16::MAX - 1 {
60 self.0 += 1;
61 }
62 }
63}
64
65#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
67pub struct LayerName(pub SmallVec<[AtomIdent; 1]>);
68
69impl LayerName {
70 pub fn new_empty() -> Self {
73 Self(Default::default())
74 }
75
76 pub fn new_anonymous() -> Self {
78 use std::sync::atomic::{AtomicUsize, Ordering};
79 static NEXT_ANONYMOUS_LAYER_NAME: AtomicUsize = AtomicUsize::new(0);
80
81 let mut name = SmallVec::new();
82 let next_id = NEXT_ANONYMOUS_LAYER_NAME.fetch_add(1, Ordering::Relaxed);
83 name.push(AtomIdent::from(&*format!("-moz-anon-layer({})", next_id)));
87
88 LayerName(name)
89 }
90
91 pub fn layer_names(&self) -> &[AtomIdent] {
94 &self.0
95 }
96}
97
98impl Parse for LayerName {
99 fn parse<'i, 't>(
100 _: &ParserContext,
101 input: &mut Parser<'i, 't>,
102 ) -> Result<Self, ParseError<'i>> {
103 let mut result = SmallVec::new();
104 result.push(AtomIdent::from(&**input.expect_ident()?));
105 loop {
106 let next_name = input.try_parse(|input| -> Result<AtomIdent, ParseError<'i>> {
107 match input.next_including_whitespace()? {
108 Token::Delim('.') => {},
109 other => {
110 let t = other.clone();
111 return Err(input.new_unexpected_token_error(t));
112 },
113 }
114
115 let name = match input.next_including_whitespace()? {
116 Token::Ident(ref ident) => ident,
117 other => {
118 let t = other.clone();
119 return Err(input.new_unexpected_token_error(t));
120 },
121 };
122
123 Ok(AtomIdent::from(&**name))
124 });
125
126 match next_name {
127 Ok(name) => result.push(name),
128 Err(..) => break,
129 }
130 }
131 Ok(LayerName(result))
132 }
133}
134
135impl ToCss for LayerName {
136 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
137 where
138 W: Write,
139 {
140 let mut first = true;
141 for name in self.0.iter() {
142 if !first {
143 dest.write_char('.')?;
144 }
145 first = false;
146 name.to_css(dest)?;
147 }
148 Ok(())
149 }
150}
151
152#[derive(Debug, ToShmem)]
153pub struct LayerBlockRule {
156 pub name: Option<LayerName>,
158 pub rules: Arc<Locked<CssRules>>,
160 pub source_location: SourceLocation,
162}
163
164impl ToCssWithGuard for LayerBlockRule {
165 fn to_css(
166 &self,
167 guard: &SharedRwLockReadGuard,
168 dest: &mut style_traits::CssStringWriter,
169 ) -> fmt::Result {
170 dest.write_str("@layer")?;
171 if let Some(ref name) = self.name {
172 dest.write_char(' ')?;
173 name.to_css(&mut CssWriter::new(dest))?;
174 }
175 self.rules.read_with(guard).to_css_block(guard, dest)
176 }
177}
178
179impl DeepCloneWithLock for LayerBlockRule {
180 fn deep_clone_with_lock(&self, lock: &SharedRwLock, guard: &SharedRwLockReadGuard) -> Self {
181 Self {
182 name: self.name.clone(),
183 rules: Arc::new(
184 lock.wrap(
185 self.rules
186 .read_with(guard)
187 .deep_clone_with_lock(lock, guard),
188 ),
189 ),
190 source_location: self.source_location.clone(),
191 }
192 }
193}
194
195#[derive(Clone, Debug, ToShmem)]
199pub struct LayerStatementRule {
200 pub names: Vec<LayerName>,
202 pub source_location: SourceLocation,
204}
205
206impl ToCssWithGuard for LayerStatementRule {
207 fn to_css(
208 &self,
209 _: &SharedRwLockReadGuard,
210 dest: &mut style_traits::CssStringWriter,
211 ) -> fmt::Result {
212 let mut writer = CssWriter::new(dest);
213 writer.write_str("@layer ")?;
214 let mut first = true;
215 for name in &*self.names {
216 if !first {
217 writer.write_str(", ")?;
218 }
219 first = false;
220 name.to_css(&mut writer)?;
221 }
222 writer.write_char(';')
223 }
224}