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)]
34#[typed(todo_derive_fields)]
35pub struct Rect<T>(pub T, pub T, pub T, pub T);
36
37impl<T> Rect<T> {
38 pub fn new(first: T, second: T, third: T, fourth: T) -> Self {
40 Rect(first, second, third, fourth)
41 }
42}
43
44impl<T> Rect<T>
45where
46 T: Clone,
47{
48 pub fn all(v: T) -> Self {
50 Rect::new(v.clone(), v.clone(), v.clone(), v)
51 }
52
53 pub fn parse_with<'i, 't, Parse>(
55 context: &ParserContext,
56 input: &mut Parser<'i, 't>,
57 parse: Parse,
58 ) -> Result<Self, ParseError<'i>>
59 where
60 Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
61 {
62 let first = parse(context, input)?;
63 let second = if let Ok(second) = input.try_parse(|i| parse(context, i)) {
64 second
65 } else {
66 return Ok(Self::new(
68 first.clone(),
69 first.clone(),
70 first.clone(),
71 first,
72 ));
73 };
74 let third = if let Ok(third) = input.try_parse(|i| parse(context, i)) {
75 third
76 } else {
77 return Ok(Self::new(first.clone(), second.clone(), first, second));
79 };
80 let fourth = if let Ok(fourth) = input.try_parse(|i| parse(context, i)) {
81 fourth
82 } else {
83 return Ok(Self::new(first, second.clone(), third, second));
85 };
86 Ok(Self::new(first, second, third, fourth))
88 }
89
90 pub fn parse_all_components_with<'i, 't, Parse>(
93 context: &ParserContext,
94 input: &mut Parser<'i, 't>,
95 parse: Parse,
96 ) -> Result<Self, ParseError<'i>>
97 where
98 Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
99 {
100 let first = parse(context, input)?;
101 let second = parse(context, input)?;
102 let third = parse(context, input)?;
103 let fourth = parse(context, input)?;
104 Ok(Self::new(first, second, third, fourth))
106 }
107}
108
109impl<T> Parse for Rect<T>
110where
111 T: Clone + Parse,
112{
113 #[inline]
114 fn parse<'i, 't>(
115 context: &ParserContext,
116 input: &mut Parser<'i, 't>,
117 ) -> Result<Self, ParseError<'i>> {
118 Self::parse_with(context, input, T::parse)
119 }
120}
121
122impl<T> ToCss for Rect<T>
123where
124 T: PartialEq + ToCss,
125{
126 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
127 where
128 W: Write,
129 {
130 self.0.to_css(dest)?;
131 let same_vertical = self.0 == self.2;
132 let same_horizontal = self.1 == self.3;
133 if same_vertical && same_horizontal && self.0 == self.1 {
134 return Ok(());
135 }
136 dest.write_char(' ')?;
137 self.1.to_css(dest)?;
138 if same_vertical && same_horizontal {
139 return Ok(());
140 }
141 dest.write_char(' ')?;
142 self.2.to_css(dest)?;
143 if same_horizontal {
144 return Ok(());
145 }
146 dest.write_char(' ')?;
147 self.3.to_css(dest)
148 }
149}