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