mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Auto merge of #17446 - servo:derive-all-the-things, r=emilio
Simplify machinery to serialise optional parts of CSS values <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17446) <!-- Reviewable:end -->
This commit is contained in:
commit
0913d65243
8 changed files with 152 additions and 131 deletions
|
@ -214,7 +214,6 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
|
||||||
|
|
||||||
<%helpers:longhand name="border-image-repeat" animation_value_type="discrete"
|
<%helpers:longhand name="border-image-repeat" animation_value_type="discrete"
|
||||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat">
|
spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat">
|
||||||
use std::fmt;
|
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
@ -227,8 +226,8 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
|
||||||
pub struct T(pub RepeatKeyword, pub RepeatKeyword);
|
pub struct T(pub RepeatKeyword, pub RepeatKeyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, ToCss)]
|
||||||
pub struct SpecifiedValue(pub RepeatKeyword,
|
pub struct SpecifiedValue(pub RepeatKeyword,
|
||||||
pub Option<RepeatKeyword>);
|
pub Option<RepeatKeyword>);
|
||||||
|
|
||||||
|
@ -238,17 +237,6 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
|
||||||
"round" => Round,
|
"round" => Round,
|
||||||
"space" => Space);
|
"space" => Space);
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
self.0.to_css(dest)?;
|
|
||||||
if let Some(second) = self.1 {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
second.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
computed_value::T(RepeatKeyword::Stretch, RepeatKeyword::Stretch)
|
computed_value::T(RepeatKeyword::Stretch, RepeatKeyword::Stretch)
|
||||||
|
|
|
@ -23,8 +23,6 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
||||||
<%helpers:longhand name="border-spacing" animation_value_type="ComputedValue" boxed="True"
|
<%helpers:longhand name="border-spacing" animation_value_type="ComputedValue" boxed="True"
|
||||||
spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing">
|
spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing">
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use std::fmt;
|
|
||||||
use style_traits::ToCss;
|
|
||||||
use values::specified::{AllowQuirks, Length};
|
use values::specified::{AllowQuirks, Length};
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
|
@ -64,8 +62,8 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
|
||||||
pub struct SpecifiedValue {
|
pub struct SpecifiedValue {
|
||||||
pub horizontal: Length,
|
pub horizontal: Length,
|
||||||
pub vertical: Option<Length>,
|
pub vertical: Option<Length>,
|
||||||
|
@ -79,19 +77,6 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
|
||||||
where W: fmt::Write,
|
|
||||||
{
|
|
||||||
self.horizontal.to_css(dest)?;
|
|
||||||
if let Some(vertical) = self.vertical.as_ref() {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
vertical.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
type ComputedValue = computed_value::T;
|
type ComputedValue = computed_value::T;
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ add_impls_for_keyword_enum!(ShapeBox);
|
||||||
/// A shape source, for some reference box.
|
/// A shape source, for some reference box.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Debug, PartialEq, ToComputedValue)]
|
#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)]
|
||||||
pub enum ShapeSource<BasicShape, ReferenceBox> {
|
pub enum ShapeSource<BasicShape, ReferenceBox> {
|
||||||
Url(SpecifiedUrl),
|
Url(SpecifiedUrl),
|
||||||
Shape(BasicShape, Option<ReferenceBox>),
|
Shape(BasicShape, Option<ReferenceBox>),
|
||||||
|
@ -126,22 +126,6 @@ impl<B, T> HasViewportPercentage for ShapeSource<B, T> {
|
||||||
fn has_viewport_percentage(&self) -> bool { false }
|
fn has_viewport_percentage(&self) -> bool { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: ToCss, T: ToCss> ToCss for ShapeSource<B, T> {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match *self {
|
|
||||||
ShapeSource::Url(ref url) => url.to_css(dest),
|
|
||||||
ShapeSource::Shape(ref shape, Some(ref ref_box)) => {
|
|
||||||
shape.to_css(dest)?;
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
ref_box.to_css(dest)
|
|
||||||
},
|
|
||||||
ShapeSource::Shape(ref shape, None) => shape.to_css(dest),
|
|
||||||
ShapeSource::Box(ref val) => val.to_css(dest),
|
|
||||||
ShapeSource::None => dest.write_str("none"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L> ToCss for InsetRect<L>
|
impl<L> ToCss for InsetRect<L>
|
||||||
where L: ToCss + PartialEq
|
where L: ToCss + PartialEq
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,7 +123,7 @@ pub enum GradientItem<Color, LengthOrPercentage> {
|
||||||
|
|
||||||
/// A color stop.
|
/// A color stop.
|
||||||
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
||||||
#[derive(Clone, Copy, HasViewportPercentage, PartialEq, ToComputedValue)]
|
#[derive(Clone, Copy, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct ColorStop<Color, LengthOrPercentage> {
|
pub struct ColorStop<Color, LengthOrPercentage> {
|
||||||
/// The color of this stop.
|
/// The color of this stop.
|
||||||
|
@ -321,19 +321,6 @@ impl<C, L> fmt::Debug for ColorStop<C, L>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, L> ToCss for ColorStop<C, L>
|
|
||||||
where C: ToCss, L: ToCss,
|
|
||||||
{
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
self.color.to_css(dest)?;
|
|
||||||
if let Some(ref position) = self.position {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
position.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C> ToCss for ImageRect<C>
|
impl<C> ToCss for ImageRect<C>
|
||||||
where C: ToCss,
|
where C: ToCss,
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,13 +6,9 @@
|
||||||
|
|
||||||
use cssparser::{BasicParseError, Parser, Token};
|
use cssparser::{BasicParseError, Parser, Token};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
use std::fmt;
|
|
||||||
use style_traits::ParseError;
|
use style_traits::ParseError;
|
||||||
#[cfg(not(feature = "gecko"))]
|
#[cfg(not(feature = "gecko"))]
|
||||||
use style_traits::StyleParseError;
|
use style_traits::StyleParseError;
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
use style_traits::ToCss;
|
|
||||||
use values::computed::{Context, Number as ComputedNumber, ToComputedValue};
|
use values::computed::{Context, Number as ComputedNumber, ToComputedValue};
|
||||||
use values::computed::effects::DropShadow as ComputedDropShadow;
|
use values::computed::effects::DropShadow as ComputedDropShadow;
|
||||||
use values::generics::effects::Filter as GenericFilter;
|
use values::generics::effects::Filter as GenericFilter;
|
||||||
|
@ -55,7 +51,7 @@ pub enum DropShadow {}
|
||||||
/// Contrary to the canonical order from the spec, the color is serialised
|
/// Contrary to the canonical order from the spec, the color is serialised
|
||||||
/// first, like in Gecko's computed values and in all Webkit's values.
|
/// first, like in Gecko's computed values and in all Webkit's values.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
|
#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
|
||||||
pub struct DropShadow {
|
pub struct DropShadow {
|
||||||
/// Color.
|
/// Color.
|
||||||
pub color: Option<Color>,
|
pub color: Option<Color>,
|
||||||
|
@ -220,25 +216,3 @@ impl ToComputedValue for DropShadow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
impl ToCss for DropShadow {
|
|
||||||
#[inline]
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: fmt::Write,
|
|
||||||
{
|
|
||||||
if let Some(ref color) = self.color {
|
|
||||||
color.to_css(dest)?;
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
}
|
|
||||||
self.horizontal.to_css(dest)?;
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
self.vertical.to_css(dest)?;
|
|
||||||
if let Some(ref blur) = self.blur {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
blur.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub type VerticalPosition = PositionComponent<Y>;
|
||||||
|
|
||||||
/// The specified value of a component of a CSS `<position>`.
|
/// The specified value of a component of a CSS `<position>`.
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, ToCss)]
|
||||||
pub enum PositionComponent<S> {
|
pub enum PositionComponent<S> {
|
||||||
/// `center`
|
/// `center`
|
||||||
Center,
|
Center,
|
||||||
|
@ -197,27 +197,6 @@ impl<S> PositionComponent<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: ToCss> ToCss for PositionComponent<S> {
|
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
||||||
match *self {
|
|
||||||
PositionComponent::Center => {
|
|
||||||
dest.write_str("center")
|
|
||||||
},
|
|
||||||
PositionComponent::Length(ref lop) => {
|
|
||||||
lop.to_css(dest)
|
|
||||||
},
|
|
||||||
PositionComponent::Side(ref keyword, ref lop) => {
|
|
||||||
keyword.to_css(dest)?;
|
|
||||||
if let Some(ref lop) = *lop {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
lop.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Side> ToComputedValue for PositionComponent<S> {
|
impl<S: Side> ToComputedValue for PositionComponent<S> {
|
||||||
type ComputedValue = ComputedLengthOrPercentage;
|
type ComputedValue = ComputedLengthOrPercentage;
|
||||||
|
|
||||||
|
|
|
@ -17,24 +17,22 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
let style = synstructure::BindStyle::Ref.into();
|
let style = synstructure::BindStyle::Ref.into();
|
||||||
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
|
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
|
||||||
let mut identifier = to_css_identifier(variant.ident.as_ref());
|
let mut identifier = to_css_identifier(variant.ident.as_ref());
|
||||||
let mut expr = if let Some((first, rest)) = bindings.split_first() {
|
let mut expr = if !bindings.is_empty() {
|
||||||
if has_free_params(&first.field.ty, &input.generics.ty_params) {
|
let mut expr = quote! {};
|
||||||
where_clause.predicates.push(where_predicate(first.field.ty.clone()));
|
for binding in bindings {
|
||||||
}
|
|
||||||
let mut expr = quote! {
|
|
||||||
::style_traits::ToCss::to_css(#first, dest)
|
|
||||||
};
|
|
||||||
for binding in rest {
|
|
||||||
if has_free_params(&binding.field.ty, &input.generics.ty_params) {
|
if has_free_params(&binding.field.ty, &input.generics.ty_params) {
|
||||||
where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
|
where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
|
||||||
}
|
}
|
||||||
expr = quote! {
|
expr = quote! {
|
||||||
#expr?;
|
#expr
|
||||||
::std::fmt::Write::write_str(dest, " ")?;
|
writer.item(#binding)?;
|
||||||
::style_traits::ToCss::to_css(#binding, dest)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
expr
|
quote! {{
|
||||||
|
let mut writer = ::style_traits::values::SequenceWriter::new(&mut *dest, " ");
|
||||||
|
#expr
|
||||||
|
Ok(())
|
||||||
|
}}
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
::std::fmt::Write::write_str(dest, #identifier)
|
::std::fmt::Write::write_str(dest, #identifier)
|
||||||
|
@ -80,7 +78,7 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl #impl_generics ::style_traits::ToCss for #name #ty_generics #where_clause {
|
impl #impl_generics ::style_traits::ToCss for #name #ty_generics #where_clause {
|
||||||
#[allow(unused_variables, unused_imports)]
|
#[allow(unused_variables)]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
|
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
|
||||||
where
|
where
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{UnicodeRange, serialize_string};
|
use cssparser::{UnicodeRange, serialize_string};
|
||||||
use std::fmt;
|
use std::fmt::{self, Write};
|
||||||
|
|
||||||
/// Serialises a value according to its CSS representation.
|
/// Serialises a value according to its CSS representation.
|
||||||
///
|
///
|
||||||
|
@ -22,7 +22,7 @@ use std::fmt;
|
||||||
/// of their fields.
|
/// of their fields.
|
||||||
pub trait ToCss {
|
pub trait ToCss {
|
||||||
/// Serialize `self` in CSS syntax, writing to `dest`.
|
/// Serialize `self` in CSS syntax, writing to `dest`.
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write;
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write;
|
||||||
|
|
||||||
/// Serialize `self` in CSS syntax and return a string.
|
/// Serialize `self` in CSS syntax and return a string.
|
||||||
///
|
///
|
||||||
|
@ -36,25 +36,151 @@ pub trait ToCss {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> ToCss for &'a T where T: ToCss + ?Sized {
|
impl<'a, T> ToCss for &'a T where T: ToCss + ?Sized {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write {
|
||||||
(*self).to_css(dest)
|
(*self).to_css(dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for str {
|
impl ToCss for str {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write {
|
||||||
serialize_string(self, dest)
|
serialize_string(self, dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for String {
|
impl ToCss for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write {
|
||||||
serialize_string(self, dest)
|
serialize_string(self, dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> ToCss for Option<T>
|
||||||
|
where
|
||||||
|
T: ToCss,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write {
|
||||||
|
self.as_ref().map_or(Ok(()), |value| value.to_css(dest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience wrapper to serialise CSS values separated by a given string.
|
||||||
|
pub struct SequenceWriter<'a, W> {
|
||||||
|
writer: TrackedWriter<W>,
|
||||||
|
separator: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W> SequenceWriter<'a, W>
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
/// Create a new sequence writer.
|
||||||
|
#[inline]
|
||||||
|
pub fn new(writer: W, separator: &'a str) -> Self {
|
||||||
|
SequenceWriter {
|
||||||
|
writer: TrackedWriter::new(writer),
|
||||||
|
separator: separator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialises a CSS value, writing any separator as necessary.
|
||||||
|
///
|
||||||
|
/// The separator is never written before any `item` produces any output,
|
||||||
|
/// and is written in subsequent calls only if the `item` produces some
|
||||||
|
/// output on its own again. This lets us handle `Option<T>` fields by
|
||||||
|
/// just not printing anything on `None`.
|
||||||
|
#[inline]
|
||||||
|
pub fn item<T>(&mut self, item: &T) -> fmt::Result
|
||||||
|
where
|
||||||
|
T: ToCss,
|
||||||
|
{
|
||||||
|
if self.writer.has_written {
|
||||||
|
item.to_css(&mut PrefixedWriter::new(&mut self.writer, self.separator))
|
||||||
|
} else {
|
||||||
|
item.to_css(&mut self.writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TrackedWriter<W> {
|
||||||
|
writer: W,
|
||||||
|
has_written: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W> TrackedWriter<W>
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn new(writer: W) -> Self {
|
||||||
|
TrackedWriter {
|
||||||
|
writer: writer,
|
||||||
|
has_written: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W> Write for TrackedWriter<W>
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
if !s.is_empty() {
|
||||||
|
self.has_written = true;
|
||||||
|
}
|
||||||
|
self.writer.write_str(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_char(&mut self, c: char) -> fmt::Result {
|
||||||
|
self.has_written = true;
|
||||||
|
self.writer.write_char(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PrefixedWriter<'a, W> {
|
||||||
|
writer: W,
|
||||||
|
prefix: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W> PrefixedWriter<'a, W>
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn new(writer: W, prefix: &'a str) -> Self {
|
||||||
|
PrefixedWriter {
|
||||||
|
writer: writer,
|
||||||
|
prefix: Some(prefix),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, W> Write for PrefixedWriter<'a, W>
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
if !s.is_empty() {
|
||||||
|
if let Some(prefix) = self.prefix.take() {
|
||||||
|
self.writer.write_str(prefix)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.writer.write_str(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_char(&mut self, c: char) -> fmt::Result {
|
||||||
|
if let Some(prefix) = self.prefix.take() {
|
||||||
|
self.writer.write_str(prefix)?;
|
||||||
|
}
|
||||||
|
self.writer.write_char(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Type used as the associated type in the `OneOrMoreSeparated` trait on a
|
/// Type used as the associated type in the `OneOrMoreSeparated` trait on a
|
||||||
/// type to indicate that a serialized list of elements of this type is
|
/// type to indicate that a serialized list of elements of this type is
|
||||||
/// separated by commas.
|
/// separated by commas.
|
||||||
|
@ -103,7 +229,7 @@ impl OneOrMoreSeparated for UnicodeRange {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ToCss for Vec<T> where T: ToCss + OneOrMoreSeparated {
|
impl<T> ToCss for Vec<T> where T: ToCss + OneOrMoreSeparated {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write {
|
||||||
let mut iter = self.iter();
|
let mut iter = self.iter();
|
||||||
iter.next().unwrap().to_css(dest)?;
|
iter.next().unwrap().to_css(dest)?;
|
||||||
for item in iter {
|
for item in iter {
|
||||||
|
@ -116,14 +242,14 @@ impl<T> ToCss for Vec<T> where T: ToCss + OneOrMoreSeparated {
|
||||||
|
|
||||||
impl<T> ToCss for Box<T> where T: ?Sized + ToCss {
|
impl<T> ToCss for Box<T> where T: ?Sized + ToCss {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||||
where W: fmt::Write,
|
where W: Write,
|
||||||
{
|
{
|
||||||
(**self).to_css(dest)
|
(**self).to_css(dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for Au {
|
impl ToCss for Au {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write {
|
||||||
write!(dest, "{}px", self.to_f64_px())
|
write!(dest, "{}px", self.to_f64_px())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +257,7 @@ impl ToCss for Au {
|
||||||
macro_rules! impl_to_css_for_predefined_type {
|
macro_rules! impl_to_css_for_predefined_type {
|
||||||
($name: ty) => {
|
($name: ty) => {
|
||||||
impl<'a> ToCss for $name {
|
impl<'a> ToCss for $name {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: Write {
|
||||||
::cssparser::ToCss::to_css(self, dest)
|
::cssparser::ToCss::to_css(self, dest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue