use super::CustomIdent;
use crate::counter_style::{parse_counter_style_name, Symbols};
use crate::parser::{Parse, ParserContext};
use crate::Zero;
use cssparser::Parser;
use std::ops::Add;
use style_traits::{KeywordsCollectFn, ParseError, SpecifiedValueInfo, StyleParseErrorKind};
pub mod animation;
pub mod background;
pub mod basic_shape;
pub mod border;
#[path = "box.rs"]
pub mod box_;
pub mod calc;
pub mod color;
pub mod column;
pub mod counters;
pub mod easing;
pub mod effects;
pub mod flex;
pub mod font;
pub mod grid;
pub mod image;
pub mod length;
pub mod motion;
pub mod page;
pub mod position;
pub mod ratio;
pub mod rect;
pub mod size;
pub mod svg;
pub mod text;
pub mod transform;
pub mod ui;
pub mod url;
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Parse,
PartialEq,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(u8)]
pub enum SymbolsType {
Cyclic,
Numeric,
Alphabetic,
Symbolic,
Fixed,
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem)]
#[repr(u8)]
pub enum CounterStyle {
Name(CustomIdent),
#[css(function)]
Symbols(#[css(skip_if = "is_symbolic")] SymbolsType, Symbols),
}
#[inline]
fn is_symbolic(symbols_type: &SymbolsType) -> bool {
*symbols_type == SymbolsType::Symbolic
}
impl CounterStyle {
pub fn disc() -> Self {
CounterStyle::Name(CustomIdent(atom!("disc")))
}
pub fn decimal() -> Self {
CounterStyle::Name(CustomIdent(atom!("decimal")))
}
#[inline]
pub fn is_bullet(&self) -> bool {
match self {
CounterStyle::Name(CustomIdent(ref name)) => {
name == &atom!("disc") ||
name == &atom!("circle") ||
name == &atom!("square") ||
name == &atom!("disclosure-closed") ||
name == &atom!("disclosure-open")
},
_ => false,
}
}
}
impl Parse for CounterStyle {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(name) = input.try_parse(|i| parse_counter_style_name(i)) {
return Ok(CounterStyle::Name(name));
}
input.expect_function_matching("symbols")?;
input.parse_nested_block(|input| {
let symbols_type = input
.try_parse(SymbolsType::parse)
.unwrap_or(SymbolsType::Symbolic);
let symbols = Symbols::parse(context, input)?;
if (symbols_type == SymbolsType::Alphabetic || symbols_type == SymbolsType::Numeric) &&
symbols.0.len() < 2
{
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(CounterStyle::Symbols(symbols_type, symbols))
})
}
}
impl SpecifiedValueInfo for CounterStyle {
fn collect_completion_keywords(f: KeywordsCollectFn) {
macro_rules! predefined {
($($name:expr,)+) => {
f(&["symbols", $($name,)+])
}
}
include!("../../counter_style/predefined.rs");
}
}
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
Deserialize,
Hash,
MallocSizeOf,
PartialEq,
PartialOrd,
SpecifiedValueInfo,
Serialize,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(transparent)]
pub struct NonNegative<T>(pub T);
impl<T: Add<Output = T>> Add<NonNegative<T>> for NonNegative<T> {
type Output = Self;
fn add(self, other: Self) -> Self {
NonNegative(self.0 + other.0)
}
}
impl<T: Zero> Zero for NonNegative<T> {
fn is_zero(&self) -> bool {
self.0.is_zero()
}
fn zero() -> Self {
NonNegative(T::zero())
}
}
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
PartialOrd,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
pub struct GreaterThanOrEqualToOne<T>(pub T);
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
Hash,
MallocSizeOf,
PartialEq,
PartialOrd,
SpecifiedValueInfo,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(transparent)]
pub struct ZeroToOne<T>(pub T);
#[allow(missing_docs)]
#[derive(
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[css(function = "rect", comma)]
#[repr(C)]
pub struct GenericClipRect<LengthOrAuto> {
pub top: LengthOrAuto,
pub right: LengthOrAuto,
pub bottom: LengthOrAuto,
pub left: LengthOrAuto,
}
pub use self::GenericClipRect as ClipRect;
#[allow(missing_docs)]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[repr(C, u8)]
pub enum GenericClipRectOrAuto<R> {
Auto,
Rect(R),
}
pub use self::GenericClipRectOrAuto as ClipRectOrAuto;
impl<L> ClipRectOrAuto<L> {
#[inline]
pub fn auto() -> Self {
ClipRectOrAuto::Auto
}
#[inline]
pub fn is_auto(&self) -> bool {
matches!(*self, ClipRectOrAuto::Auto)
}
}
pub use page::PageSize;
#[allow(missing_docs)]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
Serialize,
Deserialize,
)]
#[repr(C, u8)]
pub enum Optional<T> {
#[css(skip)]
None,
Some(T),
}
impl<T> Optional<T> {
pub fn is_some(&self) -> bool {
matches!(*self, Self::Some(..))
}
pub fn is_none(&self) -> bool {
matches!(*self, Self::None)
}
pub fn into_rust(self) -> Option<T> {
match self {
Self::Some(v) => Some(v),
Self::None => None,
}
}
pub fn as_ref(&self) -> Option<&T> {
match *self {
Self::Some(ref v) => Some(v),
Self::None => None,
}
}
}
impl<T> From<Option<T>> for Optional<T> {
fn from(rust: Option<T>) -> Self {
match rust {
Some(t) => Self::Some(t),
None => Self::None,
}
}
}