1use crate::parser::{Parse, ParserContext};
8use cssparser::Parser;
9use std::fmt::{self, Write};
10use style_traits::{CssWriter, ParseError, ToCss};
11
12#[derive(
15 Animate,
16 Clone,
17 ComputeSquaredDistance,
18 Copy,
19 Debug,
20 Deserialize,
21 MallocSizeOf,
22 PartialEq,
23 SpecifiedValueInfo,
24 Serialize,
25 ToAnimatedValue,
26 ToAnimatedZero,
27 ToComputedValue,
28 ToResolvedValue,
29 ToShmem,
30)]
31#[repr(C)]
32pub struct Rect<T>(pub T, pub T, pub T, pub T);
33
34impl<T> Rect<T> {
35 pub fn new(first: T, second: T, third: T, fourth: T) -> Self {
37 Rect(first, second, third, fourth)
38 }
39}
40
41impl<T> Rect<T>
42where
43 T: Clone,
44{
45 pub fn all(v: T) -> Self {
47 Rect::new(v.clone(), v.clone(), v.clone(), v)
48 }
49
50 pub fn parse_with<'i, 't, Parse>(
52 context: &ParserContext,
53 input: &mut Parser<'i, 't>,
54 parse: Parse,
55 ) -> Result<Self, ParseError<'i>>
56 where
57 Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
58 {
59 let first = parse(context, input)?;
60 let second = if let Ok(second) = input.try_parse(|i| parse(context, i)) {
61 second
62 } else {
63 return Ok(Self::new(
65 first.clone(),
66 first.clone(),
67 first.clone(),
68 first,
69 ));
70 };
71 let third = if let Ok(third) = input.try_parse(|i| parse(context, i)) {
72 third
73 } else {
74 return Ok(Self::new(first.clone(), second.clone(), first, second));
76 };
77 let fourth = if let Ok(fourth) = input.try_parse(|i| parse(context, i)) {
78 fourth
79 } else {
80 return Ok(Self::new(first, second.clone(), third, second));
82 };
83 Ok(Self::new(first, second, third, fourth))
85 }
86
87 pub fn parse_all_components_with<'i, 't, Parse>(
90 context: &ParserContext,
91 input: &mut Parser<'i, 't>,
92 parse: Parse,
93 ) -> Result<Self, ParseError<'i>>
94 where
95 Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
96 {
97 let first = parse(context, input)?;
98 let second = parse(context, input)?;
99 let third = parse(context, input)?;
100 let fourth = parse(context, input)?;
101 Ok(Self::new(first, second, third, fourth))
103 }
104}
105
106impl<T> Parse for Rect<T>
107where
108 T: Clone + Parse,
109{
110 #[inline]
111 fn parse<'i, 't>(
112 context: &ParserContext,
113 input: &mut Parser<'i, 't>,
114 ) -> Result<Self, ParseError<'i>> {
115 Self::parse_with(context, input, T::parse)
116 }
117}
118
119impl<T> ToCss for Rect<T>
120where
121 T: PartialEq + ToCss,
122{
123 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
124 where
125 W: Write,
126 {
127 self.0.to_css(dest)?;
128 let same_vertical = self.0 == self.2;
129 let same_horizontal = self.1 == self.3;
130 if same_vertical && same_horizontal && self.0 == self.1 {
131 return Ok(());
132 }
133 dest.write_char(' ')?;
134 self.1.to_css(dest)?;
135 if same_vertical && same_horizontal {
136 return Ok(());
137 }
138 dest.write_char(' ')?;
139 self.2.to_css(dest)?;
140 if same_horizontal {
141 return Ok(());
142 }
143 dest.write_char(' ')?;
144 self.3.to_css(dest)
145 }
146}