Add support for parsing Taffy style types from string (#929)
1//! A typed representation of [CSS style properties](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) in Rust. Used as input to layout computation.
2mod alignment;
3mod available_space;
4mod compact_length;
5mod dimension;
6
7#[cfg(feature = "block_layout")]
8mod block;
9#[cfg(feature = "flexbox")]
10mod flex;
11#[cfg(feature = "float_layout")]
12mod float;
13#[cfg(feature = "grid")]
14mod grid;
15
16pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
17pub use self::available_space::AvailableSpace;
18pub use self::compact_length::CompactLength;
19pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto};
20use crate::sys::DefaultCheapStr;
21
22#[cfg(feature = "block_layout")]
23pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};
24#[cfg(feature = "flexbox")]
25pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
26#[cfg(feature = "float_layout")]
27pub use self::float::{Clear, Float, FloatDirection};
28#[cfg(feature = "grid")]
29pub use self::grid::{
30 GenericGridPlacement, GenericGridTemplateComponent, GenericRepetition, GridAutoFlow, GridAutoTracks,
31 GridContainerStyle, GridItemStyle, GridPlacement, GridTemplateComponent, GridTemplateRepetition,
32 GridTemplateTracks, MaxTrackSizingFunction, MinTrackSizingFunction, RepetitionCount, TrackSizingFunction,
33};
34#[cfg(feature = "grid")]
35pub(crate) use self::grid::{GridAreaAxis, GridAreaEnd};
36#[cfg(feature = "grid")]
37pub use self::grid::{GridTemplateArea, NamedGridLine, TemplateLineNames};
38#[cfg(feature = "grid")]
39pub(crate) use self::grid::{NonNamedGridPlacement, OriginZeroGridPlacement};
40
41use crate::geometry::{Point, Rect, Size};
42use crate::style_helpers::TaffyAuto as _;
43use core::fmt::Debug;
44
45#[cfg(feature = "grid")]
46use crate::geometry::Line;
47#[cfg(feature = "serde")]
48use crate::style_helpers;
49#[cfg(feature = "grid")]
50use crate::util::sys::GridTrackVec;
51
52use crate::sys::String;
53
54/// Trait that represents a cheaply clonable string. If you're unsure what to use here
55/// consider `Arc<str>` or `string_cache::Atom`.
56#[cfg(any(feature = "alloc", feature = "std"))]
57pub trait CheapCloneStr:
58 AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
59{
60}
61#[cfg(any(feature = "alloc", feature = "std"))]
62impl<T> CheapCloneStr for T where
63 T: AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
64{
65}
66
67/// Trait that represents a cheaply clonable string. If you're unsure what to use here
68/// consider `Arc<str>` or `string_cache::Atom`.
69#[cfg(not(any(feature = "alloc", feature = "std")))]
70pub trait CheapCloneStr {}
71#[cfg(not(any(feature = "alloc", feature = "std")))]
72impl<T> CheapCloneStr for T {}
73
74/// The core set of styles that are shared between all CSS layout nodes
75///
76/// Note that all methods come with a default implementation which simply returns the default value for that style property
77/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need
78/// to override the default implementation for each style property that your style type actually supports.
79pub trait CoreStyle {
80 /// The type of custom identifiers used to identify named grid lines and areas
81 type CustomIdent: CheapCloneStr;
82
83 /// Which box generation mode should be used
84 #[inline(always)]
85 fn box_generation_mode(&self) -> BoxGenerationMode {
86 BoxGenerationMode::DEFAULT
87 }
88 /// Is block layout?
89 #[inline(always)]
90 fn is_block(&self) -> bool {
91 false
92 }
93 /// Is it a compressible replaced element?
94 /// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
95 #[inline(always)]
96 fn is_compressible_replaced(&self) -> bool {
97 false
98 }
99 /// Which box do size styles apply to
100 #[inline(always)]
101 fn box_sizing(&self) -> BoxSizing {
102 BoxSizing::BorderBox
103 }
104
105 // Overflow properties
106 /// How children overflowing their container should affect layout
107 #[inline(always)]
108 fn overflow(&self) -> Point<Overflow> {
109 Style::<Self::CustomIdent>::DEFAULT.overflow
110 }
111 /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
112 #[inline(always)]
113 fn scrollbar_width(&self) -> f32 {
114 0.0
115 }
116
117 // Position properties
118 /// What should the `position` value of this struct use as a base offset?
119 #[inline(always)]
120 fn position(&self) -> Position {
121 Style::<Self::CustomIdent>::DEFAULT.position
122 }
123 /// How should the position of this element be tweaked relative to the layout defined?
124 #[inline(always)]
125 fn inset(&self) -> Rect<LengthPercentageAuto> {
126 Style::<Self::CustomIdent>::DEFAULT.inset
127 }
128
129 // Size properies
130 /// Sets the initial size of the item
131 #[inline(always)]
132 fn size(&self) -> Size<Dimension> {
133 Style::<Self::CustomIdent>::DEFAULT.size
134 }
135 /// Controls the minimum size of the item
136 #[inline(always)]
137 fn min_size(&self) -> Size<Dimension> {
138 Style::<Self::CustomIdent>::DEFAULT.min_size
139 }
140 /// Controls the maximum size of the item
141 #[inline(always)]
142 fn max_size(&self) -> Size<Dimension> {
143 Style::<Self::CustomIdent>::DEFAULT.max_size
144 }
145 /// Sets the preferred aspect ratio for the item
146 /// The ratio is calculated as width divided by height.
147 #[inline(always)]
148 fn aspect_ratio(&self) -> Option<f32> {
149 Style::<Self::CustomIdent>::DEFAULT.aspect_ratio
150 }
151
152 // Spacing Properties
153 /// How large should the margin be on each side?
154 #[inline(always)]
155 fn margin(&self) -> Rect<LengthPercentageAuto> {
156 Style::<Self::CustomIdent>::DEFAULT.margin
157 }
158 /// How large should the padding be on each side?
159 #[inline(always)]
160 fn padding(&self) -> Rect<LengthPercentage> {
161 Style::<Self::CustomIdent>::DEFAULT.padding
162 }
163 /// How large should the border be on each side?
164 #[inline(always)]
165 fn border(&self) -> Rect<LengthPercentage> {
166 Style::<Self::CustomIdent>::DEFAULT.border
167 }
168}
169
170/// Sets the layout used for the children of this node
171///
172/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
173#[derive(Copy, Clone, PartialEq, Eq, Debug)]
174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175pub enum Display {
176 /// The children will follow the block layout algorithm
177 #[cfg(feature = "block_layout")]
178 Block,
179 /// The children will follow the flexbox layout algorithm
180 #[cfg(feature = "flexbox")]
181 Flex,
182 /// The children will follow the CSS Grid layout algorithm
183 #[cfg(feature = "grid")]
184 Grid,
185 /// The node is hidden, and it's children will also be hidden
186 None,
187}
188
189impl Display {
190 /// The default Display mode
191 #[cfg(feature = "flexbox")]
192 pub const DEFAULT: Display = Display::Flex;
193
194 /// The default Display mode
195 #[cfg(all(feature = "grid", not(feature = "flexbox")))]
196 pub const DEFAULT: Display = Display::Grid;
197
198 /// The default Display mode
199 #[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
200 pub const DEFAULT: Display = Display::Block;
201
202 /// The default Display mode
203 #[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
204 pub const DEFAULT: Display = Display::None;
205}
206
207impl Default for Display {
208 fn default() -> Self {
209 Self::DEFAULT
210 }
211}
212
213#[cfg(feature = "parse")]
214crate::util::parse::impl_parse_for_keyword_enum!(Display,
215 "none" => None,
216 #[cfg(feature = "flexbox")]
217 "flex" => Flex,
218 #[cfg(feature = "grid")]
219 "grid" => Grid,
220 #[cfg(feature = "block_layout")]
221 "block" => Block,
222);
223
224impl core::fmt::Display for Display {
225 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
226 match self {
227 Display::None => write!(f, "NONE"),
228 #[cfg(feature = "block_layout")]
229 Display::Block => write!(f, "BLOCK"),
230 #[cfg(feature = "flexbox")]
231 Display::Flex => write!(f, "FLEX"),
232 #[cfg(feature = "grid")]
233 Display::Grid => write!(f, "GRID"),
234 }
235 }
236}
237
238/// An abstracted version of the CSS `display` property where any value other than "none" is represented by "normal"
239/// See: <https://www.w3.org/TR/css-display-3/#box-generation>
240#[derive(Copy, Clone, PartialEq, Eq, Debug)]
241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
242pub enum BoxGenerationMode {
243 /// The node generates a box in the regular way
244 Normal,
245 /// The node and it's descendants generate no boxes (they are hidden)
246 None,
247}
248
249impl BoxGenerationMode {
250 /// The default of BoxGenerationMode
251 pub const DEFAULT: BoxGenerationMode = BoxGenerationMode::Normal;
252}
253
254impl Default for BoxGenerationMode {
255 fn default() -> Self {
256 Self::DEFAULT
257 }
258}
259
260/// The positioning strategy for this item.
261///
262/// This controls both how the origin is determined for the [`Style::position`] field,
263/// and whether or not the item will be controlled by flexbox's layout algorithm.
264///
265/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
266/// which can be unintuitive.
267///
268/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
269#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
270#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
271pub enum Position {
272 /// The offset is computed relative to the final position given by the layout algorithm.
273 /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
274 #[default]
275 Relative,
276 /// The offset is computed relative to this item's closest positioned ancestor, if any.
277 /// Otherwise, it is placed relative to the origin.
278 /// No space is created for the item in the page layout, and its size will not be altered.
279 ///
280 /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
281 Absolute,
282}
283
284#[cfg(feature = "parse")]
285crate::util::parse::impl_parse_for_keyword_enum!(Position,
286 "relative" => Relative,
287 "absolute" => Absolute,
288);
289
290/// Specifies whether size styles for this node are assigned to the node's "content box" or "border box"
291///
292/// - The "content box" is the node's inner size excluding padding, border and margin
293/// - The "border box" is the node's outer size including padding and border (but still excluding margin)
294///
295/// This property modifies the application of the following styles:
296///
297/// - `size`
298/// - `min_size`
299/// - `max_size`
300/// - `flex_basis`
301///
302/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing>
303#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
304#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
305pub enum BoxSizing {
306 /// Size styles such size, min_size, max_size specify the box's "border box" (the size excluding margin but including padding/border)
307 #[default]
308 BorderBox,
309 /// Size styles such size, min_size, max_size specify the box's "content box" (the size excluding padding/border/margin)
310 ContentBox,
311}
312
313#[cfg(feature = "parse")]
314crate::util::parse::impl_parse_for_keyword_enum!(BoxSizing,
315 "border-box" => BorderBox,
316 "content-box" => ContentBox,
317);
318
319/// How children overflowing their container should affect layout
320///
321/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
322/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
323/// the main ones being:
324///
325/// - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based
326/// - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property)
327///
328/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for
329/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`.
330///
331/// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
332#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
334pub enum Overflow {
335 /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
336 /// Content that overflows this node *should* contribute to the scroll region of its parent.
337 #[default]
338 Visible,
339 /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
340 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
341 Clip,
342 /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
343 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
344 Hidden,
345 /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved
346 /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property.
347 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
348 Scroll,
349}
350
351impl Overflow {
352 /// Returns true for overflow modes that contain their contents (`Overflow::Hidden`, `Overflow::Scroll`, `Overflow::Auto`)
353 /// or else false for overflow modes that allow their contains to spill (`Overflow::Visible`).
354 #[inline(always)]
355 pub fn is_scroll_container(self) -> bool {
356 match self {
357 Self::Visible | Self::Clip => false,
358 Self::Hidden | Self::Scroll => true,
359 }
360 }
361
362 /// Returns `Some(0.0)` if the overflow mode would cause the automatic minimum size of a Flexbox or CSS Grid item
363 /// to be `0`. Else returns None.
364 #[inline(always)]
365 pub(crate) fn maybe_into_automatic_min_size(self) -> Option<f32> {
366 match self.is_scroll_container() {
367 true => Some(0.0),
368 false => None,
369 }
370 }
371}
372
373#[cfg(feature = "parse")]
374crate::util::parse::impl_parse_for_keyword_enum!(Overflow,
375 "visible" => Visible,
376 "hidden" => Hidden,
377 "clip" => Clip,
378 "scroll" => Scroll,
379);
380
381/// A typed representation of the CSS style information for a single node.
382///
383/// The most important idea in flexbox is the notion of a "main" and "cross" axis, which are always perpendicular to each other.
384/// The orientation of these axes are controlled via the [`FlexDirection`] field of this struct.
385///
386/// This struct follows the [CSS equivalent](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) directly;
387/// information about the behavior on the web should transfer directly.
388///
389/// Detailed information about the exact behavior of each of these fields
390/// can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) by searching for the field name.
391/// The distinction between margin, padding and border is explained well in
392/// this [introduction to the box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model).
393///
394/// If the behavior does not match the flexbox layout algorithm on the web, please file a bug!
395#[derive(Clone, PartialEq, Debug)]
396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
397#[cfg_attr(feature = "serde", serde(default))]
398pub struct Style<S: CheapCloneStr = DefaultCheapStr> {
399 /// This is a dummy field which is necessary to make Taffy compile with the `grid` feature disabled
400 /// It should always be set to `core::marker::PhantomData`.
401 pub dummy: core::marker::PhantomData<S>,
402 /// What layout strategy should be used?
403 pub display: Display,
404 /// Whether a child is display:table or not. This affects children of block layouts.
405 /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
406 pub item_is_table: bool,
407 /// Is it a replaced element like an image or form field?
408 /// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
409 pub item_is_replaced: bool,
410 /// Should size styles apply to the content box or the border box of the node
411 pub box_sizing: BoxSizing,
412
413 // Overflow properties
414 /// How children overflowing their container should affect layout
415 pub overflow: Point<Overflow>,
416 /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
417 pub scrollbar_width: f32,
418
419 #[cfg(feature = "float_layout")]
420 /// Should the box be floated
421 pub float: Float,
422 #[cfg(feature = "float_layout")]
423 /// Should the box clear floats
424 pub clear: Clear,
425
426 // Position properties
427 /// What should the `position` value of this struct use as a base offset?
428 pub position: Position,
429 /// How should the position of this element be tweaked relative to the layout defined?
430 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
431 pub inset: Rect<LengthPercentageAuto>,
432
433 // Size properties
434 /// Sets the initial size of the item
435 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
436 pub size: Size<Dimension>,
437 /// Controls the minimum size of the item
438 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
439 pub min_size: Size<Dimension>,
440 /// Controls the maximum size of the item
441 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
442 pub max_size: Size<Dimension>,
443 /// Sets the preferred aspect ratio for the item
444 ///
445 /// The ratio is calculated as width divided by height.
446 pub aspect_ratio: Option<f32>,
447
448 // Spacing Properties
449 /// How large should the margin be on each side?
450 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
451 pub margin: Rect<LengthPercentageAuto>,
452 /// How large should the padding be on each side?
453 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
454 pub padding: Rect<LengthPercentage>,
455 /// How large should the border be on each side?
456 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
457 pub border: Rect<LengthPercentage>,
458
459 // Alignment properties
460 /// How this node's children aligned in the cross/block axis?
461 #[cfg(any(feature = "flexbox", feature = "grid"))]
462 pub align_items: Option<AlignItems>,
463 /// How this node should be aligned in the cross/block axis
464 /// Falls back to the parents [`AlignItems`] if not set
465 #[cfg(any(feature = "flexbox", feature = "grid"))]
466 pub align_self: Option<AlignSelf>,
467 /// How this node's children should be aligned in the inline axis
468 #[cfg(feature = "grid")]
469 pub justify_items: Option<AlignItems>,
470 /// How this node should be aligned in the inline axis
471 /// Falls back to the parents [`JustifyItems`] if not set
472 #[cfg(feature = "grid")]
473 pub justify_self: Option<AlignSelf>,
474 /// How should content contained within this item be aligned in the cross/block axis
475 #[cfg(any(feature = "flexbox", feature = "grid"))]
476 pub align_content: Option<AlignContent>,
477 /// How should content contained within this item be aligned in the main/inline axis
478 #[cfg(any(feature = "flexbox", feature = "grid"))]
479 pub justify_content: Option<JustifyContent>,
480 /// How large should the gaps between items in a grid or flex container be?
481 #[cfg(any(feature = "flexbox", feature = "grid"))]
482 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
483 pub gap: Size<LengthPercentage>,
484
485 // Block container properties
486 /// How items elements should aligned in the inline axis
487 #[cfg(feature = "block_layout")]
488 pub text_align: TextAlign,
489
490 // Flexbox container properties
491 /// Which direction does the main axis flow in?
492 #[cfg(feature = "flexbox")]
493 pub flex_direction: FlexDirection,
494 /// Should elements wrap, or stay in a single line?
495 #[cfg(feature = "flexbox")]
496 pub flex_wrap: FlexWrap,
497
498 // Flexbox item properties
499 /// Sets the initial main axis size of the item
500 #[cfg(feature = "flexbox")]
501 pub flex_basis: Dimension,
502 /// The relative rate at which this item grows when it is expanding to fill space
503 ///
504 /// 0.0 is the default value, and this value must be positive.
505 #[cfg(feature = "flexbox")]
506 pub flex_grow: f32,
507 /// The relative rate at which this item shrinks when it is contracting to fit into space
508 ///
509 /// 1.0 is the default value, and this value must be positive.
510 #[cfg(feature = "flexbox")]
511 pub flex_shrink: f32,
512
513 // Grid container properies
514 /// Defines the track sizing functions (heights) of the grid rows
515 #[cfg(feature = "grid")]
516 pub grid_template_rows: GridTrackVec<GridTemplateComponent<S>>,
517 /// Defines the track sizing functions (widths) of the grid columns
518 #[cfg(feature = "grid")]
519 pub grid_template_columns: GridTrackVec<GridTemplateComponent<S>>,
520 /// Defines the size of implicitly created rows
521 #[cfg(feature = "grid")]
522 pub grid_auto_rows: GridTrackVec<TrackSizingFunction>,
523 /// Defined the size of implicitly created columns
524 #[cfg(feature = "grid")]
525 pub grid_auto_columns: GridTrackVec<TrackSizingFunction>,
526 /// Controls how items get placed into the grid for auto-placed items
527 #[cfg(feature = "grid")]
528 pub grid_auto_flow: GridAutoFlow,
529
530 // Grid container named properties
531 /// Defines the rectangular grid areas
532 #[cfg(feature = "grid")]
533 pub grid_template_areas: GridTrackVec<GridTemplateArea<S>>,
534 /// The named lines between the columns
535 #[cfg(feature = "grid")]
536 pub grid_template_column_names: GridTrackVec<GridTrackVec<S>>,
537 /// The named lines between the rows
538 #[cfg(feature = "grid")]
539 pub grid_template_row_names: GridTrackVec<GridTrackVec<S>>,
540
541 // Grid child properties
542 /// Defines which row in the grid the item should start and end at
543 #[cfg(feature = "grid")]
544 pub grid_row: Line<GridPlacement<S>>,
545 /// Defines which column in the grid the item should start and end at
546 #[cfg(feature = "grid")]
547 pub grid_column: Line<GridPlacement<S>>,
548}
549
550impl<S: CheapCloneStr> Style<S> {
551 /// The [`Default`] layout, in a form that can be used in const functions
552 pub const DEFAULT: Style<S> = Style {
553 dummy: core::marker::PhantomData,
554 display: Display::DEFAULT,
555 item_is_table: false,
556 item_is_replaced: false,
557 box_sizing: BoxSizing::BorderBox,
558 overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
559 scrollbar_width: 0.0,
560 #[cfg(feature = "float_layout")]
561 float: Float::None,
562 #[cfg(feature = "float_layout")]
563 clear: Clear::None,
564 position: Position::Relative,
565 inset: Rect::auto(),
566 margin: Rect::zero(),
567 padding: Rect::zero(),
568 border: Rect::zero(),
569 size: Size::auto(),
570 min_size: Size::auto(),
571 max_size: Size::auto(),
572 aspect_ratio: None,
573 #[cfg(any(feature = "flexbox", feature = "grid"))]
574 gap: Size::zero(),
575 // Alignment
576 #[cfg(any(feature = "flexbox", feature = "grid"))]
577 align_items: None,
578 #[cfg(any(feature = "flexbox", feature = "grid"))]
579 align_self: None,
580 #[cfg(feature = "grid")]
581 justify_items: None,
582 #[cfg(feature = "grid")]
583 justify_self: None,
584 #[cfg(any(feature = "flexbox", feature = "grid"))]
585 align_content: None,
586 #[cfg(any(feature = "flexbox", feature = "grid"))]
587 justify_content: None,
588 // Block
589 #[cfg(feature = "block_layout")]
590 text_align: TextAlign::Auto,
591 // Flexbox
592 #[cfg(feature = "flexbox")]
593 flex_direction: FlexDirection::Row,
594 #[cfg(feature = "flexbox")]
595 flex_wrap: FlexWrap::NoWrap,
596 #[cfg(feature = "flexbox")]
597 flex_grow: 0.0,
598 #[cfg(feature = "flexbox")]
599 flex_shrink: 1.0,
600 #[cfg(feature = "flexbox")]
601 flex_basis: Dimension::AUTO,
602 // Grid
603 #[cfg(feature = "grid")]
604 grid_template_rows: GridTrackVec::new(),
605 #[cfg(feature = "grid")]
606 grid_template_columns: GridTrackVec::new(),
607 #[cfg(feature = "grid")]
608 grid_template_areas: GridTrackVec::new(),
609 #[cfg(feature = "grid")]
610 grid_template_column_names: GridTrackVec::new(),
611 #[cfg(feature = "grid")]
612 grid_template_row_names: GridTrackVec::new(),
613 #[cfg(feature = "grid")]
614 grid_auto_rows: GridTrackVec::new(),
615 #[cfg(feature = "grid")]
616 grid_auto_columns: GridTrackVec::new(),
617 #[cfg(feature = "grid")]
618 grid_auto_flow: GridAutoFlow::Row,
619 #[cfg(feature = "grid")]
620 grid_row: Line { start: GridPlacement::<S>::Auto, end: GridPlacement::<S>::Auto },
621 #[cfg(feature = "grid")]
622 grid_column: Line { start: GridPlacement::<S>::Auto, end: GridPlacement::<S>::Auto },
623 };
624}
625
626impl<S: CheapCloneStr> Default for Style<S> {
627 fn default() -> Self {
628 Style::DEFAULT
629 }
630}
631
632impl<S: CheapCloneStr> CoreStyle for Style<S> {
633 type CustomIdent = S;
634
635 #[inline(always)]
636 fn box_generation_mode(&self) -> BoxGenerationMode {
637 match self.display {
638 Display::None => BoxGenerationMode::None,
639 _ => BoxGenerationMode::Normal,
640 }
641 }
642 #[inline(always)]
643 #[cfg(feature = "block_layout")]
644 fn is_block(&self) -> bool {
645 matches!(self.display, Display::Block)
646 }
647 #[inline(always)]
648 fn is_compressible_replaced(&self) -> bool {
649 self.item_is_replaced
650 }
651 #[inline(always)]
652 fn box_sizing(&self) -> BoxSizing {
653 self.box_sizing
654 }
655 #[inline(always)]
656 fn overflow(&self) -> Point<Overflow> {
657 self.overflow
658 }
659 #[inline(always)]
660 fn scrollbar_width(&self) -> f32 {
661 self.scrollbar_width
662 }
663 #[inline(always)]
664 fn position(&self) -> Position {
665 self.position
666 }
667 #[inline(always)]
668 fn inset(&self) -> Rect<LengthPercentageAuto> {
669 self.inset
670 }
671 #[inline(always)]
672 fn size(&self) -> Size<Dimension> {
673 self.size
674 }
675 #[inline(always)]
676 fn min_size(&self) -> Size<Dimension> {
677 self.min_size
678 }
679 #[inline(always)]
680 fn max_size(&self) -> Size<Dimension> {
681 self.max_size
682 }
683 #[inline(always)]
684 fn aspect_ratio(&self) -> Option<f32> {
685 self.aspect_ratio
686 }
687 #[inline(always)]
688 fn margin(&self) -> Rect<LengthPercentageAuto> {
689 self.margin
690 }
691 #[inline(always)]
692 fn padding(&self) -> Rect<LengthPercentage> {
693 self.padding
694 }
695 #[inline(always)]
696 fn border(&self) -> Rect<LengthPercentage> {
697 self.border
698 }
699}
700
701impl<T: CoreStyle> CoreStyle for &'_ T {
702 type CustomIdent = T::CustomIdent;
703
704 #[inline(always)]
705 fn box_generation_mode(&self) -> BoxGenerationMode {
706 (*self).box_generation_mode()
707 }
708 #[inline(always)]
709 fn is_block(&self) -> bool {
710 (*self).is_block()
711 }
712 #[inline(always)]
713 fn is_compressible_replaced(&self) -> bool {
714 (*self).is_compressible_replaced()
715 }
716 #[inline(always)]
717 fn box_sizing(&self) -> BoxSizing {
718 (*self).box_sizing()
719 }
720 #[inline(always)]
721 fn overflow(&self) -> Point<Overflow> {
722 (*self).overflow()
723 }
724 #[inline(always)]
725 fn scrollbar_width(&self) -> f32 {
726 (*self).scrollbar_width()
727 }
728 #[inline(always)]
729 fn position(&self) -> Position {
730 (*self).position()
731 }
732 #[inline(always)]
733 fn inset(&self) -> Rect<LengthPercentageAuto> {
734 (*self).inset()
735 }
736 #[inline(always)]
737 fn size(&self) -> Size<Dimension> {
738 (*self).size()
739 }
740 #[inline(always)]
741 fn min_size(&self) -> Size<Dimension> {
742 (*self).min_size()
743 }
744 #[inline(always)]
745 fn max_size(&self) -> Size<Dimension> {
746 (*self).max_size()
747 }
748 #[inline(always)]
749 fn aspect_ratio(&self) -> Option<f32> {
750 (*self).aspect_ratio()
751 }
752 #[inline(always)]
753 fn margin(&self) -> Rect<LengthPercentageAuto> {
754 (*self).margin()
755 }
756 #[inline(always)]
757 fn padding(&self) -> Rect<LengthPercentage> {
758 (*self).padding()
759 }
760 #[inline(always)]
761 fn border(&self) -> Rect<LengthPercentage> {
762 (*self).border()
763 }
764}
765
766#[cfg(feature = "block_layout")]
767impl<S: CheapCloneStr> BlockContainerStyle for Style<S> {
768 #[inline(always)]
769 fn text_align(&self) -> TextAlign {
770 self.text_align
771 }
772}
773
774#[cfg(feature = "block_layout")]
775impl<T: BlockContainerStyle> BlockContainerStyle for &'_ T {
776 #[inline(always)]
777 fn text_align(&self) -> TextAlign {
778 (*self).text_align()
779 }
780}
781
782#[cfg(feature = "block_layout")]
783impl<S: CheapCloneStr> BlockItemStyle for Style<S> {
784 #[inline(always)]
785 fn is_table(&self) -> bool {
786 self.item_is_table
787 }
788
789 #[cfg(feature = "float_layout")]
790 #[inline(always)]
791 fn float(&self) -> Float {
792 self.float
793 }
794
795 #[cfg(feature = "float_layout")]
796 #[inline(always)]
797 fn clear(&self) -> Clear {
798 self.clear
799 }
800}
801
802#[cfg(feature = "block_layout")]
803impl<T: BlockItemStyle> BlockItemStyle for &'_ T {
804 #[inline(always)]
805 fn is_table(&self) -> bool {
806 (*self).is_table()
807 }
808
809 #[cfg(feature = "float_layout")]
810 #[inline(always)]
811 fn float(&self) -> Float {
812 (*self).float()
813 }
814
815 #[cfg(feature = "float_layout")]
816 #[inline(always)]
817 fn clear(&self) -> Clear {
818 (*self).clear()
819 }
820}
821
822#[cfg(feature = "flexbox")]
823impl<S: CheapCloneStr> FlexboxContainerStyle for Style<S> {
824 #[inline(always)]
825 fn flex_direction(&self) -> FlexDirection {
826 self.flex_direction
827 }
828 #[inline(always)]
829 fn flex_wrap(&self) -> FlexWrap {
830 self.flex_wrap
831 }
832 #[inline(always)]
833 fn gap(&self) -> Size<LengthPercentage> {
834 self.gap
835 }
836 #[inline(always)]
837 fn align_content(&self) -> Option<AlignContent> {
838 self.align_content
839 }
840 #[inline(always)]
841 fn align_items(&self) -> Option<AlignItems> {
842 self.align_items
843 }
844 #[inline(always)]
845 fn justify_content(&self) -> Option<JustifyContent> {
846 self.justify_content
847 }
848}
849
850#[cfg(feature = "flexbox")]
851impl<T: FlexboxContainerStyle> FlexboxContainerStyle for &'_ T {
852 #[inline(always)]
853 fn flex_direction(&self) -> FlexDirection {
854 (*self).flex_direction()
855 }
856 #[inline(always)]
857 fn flex_wrap(&self) -> FlexWrap {
858 (*self).flex_wrap()
859 }
860 #[inline(always)]
861 fn gap(&self) -> Size<LengthPercentage> {
862 (*self).gap()
863 }
864 #[inline(always)]
865 fn align_content(&self) -> Option<AlignContent> {
866 (*self).align_content()
867 }
868 #[inline(always)]
869 fn align_items(&self) -> Option<AlignItems> {
870 (*self).align_items()
871 }
872 #[inline(always)]
873 fn justify_content(&self) -> Option<JustifyContent> {
874 (*self).justify_content()
875 }
876}
877
878#[cfg(feature = "flexbox")]
879impl<S: CheapCloneStr> FlexboxItemStyle for Style<S> {
880 #[inline(always)]
881 fn flex_basis(&self) -> Dimension {
882 self.flex_basis
883 }
884 #[inline(always)]
885 fn flex_grow(&self) -> f32 {
886 self.flex_grow
887 }
888 #[inline(always)]
889 fn flex_shrink(&self) -> f32 {
890 self.flex_shrink
891 }
892 #[inline(always)]
893 fn align_self(&self) -> Option<AlignSelf> {
894 self.align_self
895 }
896}
897
898#[cfg(feature = "flexbox")]
899impl<T: FlexboxItemStyle> FlexboxItemStyle for &'_ T {
900 #[inline(always)]
901 fn flex_basis(&self) -> Dimension {
902 (*self).flex_basis()
903 }
904 #[inline(always)]
905 fn flex_grow(&self) -> f32 {
906 (*self).flex_grow()
907 }
908 #[inline(always)]
909 fn flex_shrink(&self) -> f32 {
910 (*self).flex_shrink()
911 }
912 #[inline(always)]
913 fn align_self(&self) -> Option<AlignSelf> {
914 (*self).align_self()
915 }
916}
917
918#[cfg(feature = "grid")]
919impl<S: CheapCloneStr> GridContainerStyle for Style<S> {
920 type Repetition<'a>
921 = &'a GridTemplateRepetition<S>
922 where
923 Self: 'a;
924
925 type TemplateTrackList<'a>
926 = core::iter::Map<
927 core::slice::Iter<'a, GridTemplateComponent<S>>,
928 fn(&'a GridTemplateComponent<S>) -> GenericGridTemplateComponent<S, &'a GridTemplateRepetition<S>>,
929 >
930 where
931 Self: 'a;
932
933 type AutoTrackList<'a>
934 = core::iter::Copied<core::slice::Iter<'a, TrackSizingFunction>>
935 where
936 Self: 'a;
937
938 #[cfg(feature = "grid")]
939 type TemplateLineNames<'a>
940 = core::iter::Map<core::slice::Iter<'a, GridTrackVec<S>>, fn(&GridTrackVec<S>) -> core::slice::Iter<'_, S>>
941 where
942 Self: 'a;
943 #[cfg(feature = "grid")]
944 type GridTemplateAreas<'a>
945 = core::iter::Cloned<core::slice::Iter<'a, GridTemplateArea<S>>>
946 where
947 Self: 'a;
948
949 #[inline(always)]
950 fn grid_template_rows(&self) -> Option<Self::TemplateTrackList<'_>> {
951 Some(self.grid_template_rows.iter().map(|c| c.as_component_ref()))
952 }
953 #[inline(always)]
954 fn grid_template_columns(&self) -> Option<Self::TemplateTrackList<'_>> {
955 Some(self.grid_template_columns.iter().map(|c| c.as_component_ref()))
956 }
957 #[inline(always)]
958 fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
959 self.grid_auto_rows.iter().copied()
960 }
961 #[inline(always)]
962 fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
963 self.grid_auto_columns.iter().copied()
964 }
965 #[inline(always)]
966 fn grid_auto_flow(&self) -> GridAutoFlow {
967 self.grid_auto_flow
968 }
969 #[inline(always)]
970 fn gap(&self) -> Size<LengthPercentage> {
971 self.gap
972 }
973 #[inline(always)]
974 fn align_content(&self) -> Option<AlignContent> {
975 self.align_content
976 }
977 #[inline(always)]
978 fn justify_content(&self) -> Option<JustifyContent> {
979 self.justify_content
980 }
981 #[inline(always)]
982 fn align_items(&self) -> Option<AlignItems> {
983 self.align_items
984 }
985 #[inline(always)]
986 fn justify_items(&self) -> Option<AlignItems> {
987 self.justify_items
988 }
989
990 #[inline(always)]
991 #[cfg(feature = "grid")]
992 fn grid_template_areas(&self) -> Option<Self::GridTemplateAreas<'_>> {
993 Some(self.grid_template_areas.iter().cloned())
994 }
995
996 #[inline(always)]
997 #[cfg(feature = "grid")]
998 fn grid_template_column_names(&self) -> Option<Self::TemplateLineNames<'_>> {
999 Some(self.grid_template_column_names.iter().map(|names| names.iter()))
1000 }
1001
1002 #[inline(always)]
1003 #[cfg(feature = "grid")]
1004 fn grid_template_row_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1005 Some(self.grid_template_row_names.iter().map(|names| names.iter()))
1006 }
1007}
1008
1009#[cfg(feature = "grid")]
1010impl<T: GridContainerStyle> GridContainerStyle for &'_ T {
1011 type Repetition<'a>
1012 = T::Repetition<'a>
1013 where
1014 Self: 'a;
1015
1016 type TemplateTrackList<'a>
1017 = T::TemplateTrackList<'a>
1018 where
1019 Self: 'a;
1020
1021 type AutoTrackList<'a>
1022 = T::AutoTrackList<'a>
1023 where
1024 Self: 'a;
1025
1026 /// The type returned by grid_template_row_names and grid_template_column_names
1027 #[cfg(feature = "grid")]
1028 type TemplateLineNames<'a>
1029 = T::TemplateLineNames<'a>
1030 where
1031 Self: 'a;
1032 #[cfg(feature = "grid")]
1033 type GridTemplateAreas<'a>
1034 = T::GridTemplateAreas<'a>
1035 where
1036 Self: 'a;
1037
1038 #[inline(always)]
1039 fn grid_template_rows(&self) -> Option<Self::TemplateTrackList<'_>> {
1040 (*self).grid_template_rows()
1041 }
1042 #[inline(always)]
1043 fn grid_template_columns(&self) -> Option<Self::TemplateTrackList<'_>> {
1044 (*self).grid_template_columns()
1045 }
1046 #[inline(always)]
1047 fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
1048 (*self).grid_auto_rows()
1049 }
1050 #[inline(always)]
1051 fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
1052 (*self).grid_auto_columns()
1053 }
1054 #[cfg(feature = "grid")]
1055 #[inline(always)]
1056 fn grid_template_areas(&self) -> Option<Self::GridTemplateAreas<'_>> {
1057 (*self).grid_template_areas()
1058 }
1059 #[cfg(feature = "grid")]
1060 #[inline(always)]
1061 fn grid_template_column_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1062 (*self).grid_template_column_names()
1063 }
1064 #[cfg(feature = "grid")]
1065 #[inline(always)]
1066 fn grid_template_row_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1067 (*self).grid_template_row_names()
1068 }
1069 #[inline(always)]
1070 fn grid_auto_flow(&self) -> GridAutoFlow {
1071 (*self).grid_auto_flow()
1072 }
1073 #[inline(always)]
1074 fn gap(&self) -> Size<LengthPercentage> {
1075 (*self).gap()
1076 }
1077 #[inline(always)]
1078 fn align_content(&self) -> Option<AlignContent> {
1079 (*self).align_content()
1080 }
1081 #[inline(always)]
1082 fn justify_content(&self) -> Option<JustifyContent> {
1083 (*self).justify_content()
1084 }
1085 #[inline(always)]
1086 fn align_items(&self) -> Option<AlignItems> {
1087 (*self).align_items()
1088 }
1089 #[inline(always)]
1090 fn justify_items(&self) -> Option<AlignItems> {
1091 (*self).justify_items()
1092 }
1093}
1094
1095#[cfg(feature = "grid")]
1096impl<S: CheapCloneStr> GridItemStyle for Style<S> {
1097 #[inline(always)]
1098 fn grid_row(&self) -> Line<GridPlacement<S>> {
1099 // TODO: Investigate eliminating clone
1100 self.grid_row.clone()
1101 }
1102 #[inline(always)]
1103 fn grid_column(&self) -> Line<GridPlacement<S>> {
1104 // TODO: Investigate eliminating clone
1105 self.grid_column.clone()
1106 }
1107 #[inline(always)]
1108 fn align_self(&self) -> Option<AlignSelf> {
1109 self.align_self
1110 }
1111 #[inline(always)]
1112 fn justify_self(&self) -> Option<AlignSelf> {
1113 self.justify_self
1114 }
1115}
1116
1117#[cfg(feature = "grid")]
1118impl<T: GridItemStyle> GridItemStyle for &'_ T {
1119 #[inline(always)]
1120 fn grid_row(&self) -> Line<GridPlacement<Self::CustomIdent>> {
1121 (*self).grid_row()
1122 }
1123 #[inline(always)]
1124 fn grid_column(&self) -> Line<GridPlacement<Self::CustomIdent>> {
1125 (*self).grid_column()
1126 }
1127 #[inline(always)]
1128 fn align_self(&self) -> Option<AlignSelf> {
1129 (*self).align_self()
1130 }
1131 #[inline(always)]
1132 fn justify_self(&self) -> Option<AlignSelf> {
1133 (*self).justify_self()
1134 }
1135}
1136
1137#[cfg(test)]
1138mod tests {
1139 use std::sync::Arc;
1140
1141 use super::Style;
1142 use crate::sys::DefaultCheapStr;
1143 use crate::{geometry::*, style_helpers::TaffyAuto as _};
1144
1145 #[test]
1146 fn defaults_match() {
1147 #[cfg(feature = "grid")]
1148 use super::GridPlacement;
1149
1150 let old_defaults: Style<DefaultCheapStr> = Style {
1151 dummy: core::marker::PhantomData,
1152 display: Default::default(),
1153 item_is_table: false,
1154 item_is_replaced: false,
1155 box_sizing: Default::default(),
1156 #[cfg(feature = "float_layout")]
1157 float: Default::default(),
1158 #[cfg(feature = "float_layout")]
1159 clear: Default::default(),
1160 overflow: Default::default(),
1161 scrollbar_width: 0.0,
1162 position: Default::default(),
1163 #[cfg(feature = "flexbox")]
1164 flex_direction: Default::default(),
1165 #[cfg(feature = "flexbox")]
1166 flex_wrap: Default::default(),
1167 #[cfg(any(feature = "flexbox", feature = "grid"))]
1168 align_items: Default::default(),
1169 #[cfg(any(feature = "flexbox", feature = "grid"))]
1170 align_self: Default::default(),
1171 #[cfg(feature = "grid")]
1172 justify_items: Default::default(),
1173 #[cfg(feature = "grid")]
1174 justify_self: Default::default(),
1175 #[cfg(any(feature = "flexbox", feature = "grid"))]
1176 align_content: Default::default(),
1177 #[cfg(any(feature = "flexbox", feature = "grid"))]
1178 justify_content: Default::default(),
1179 inset: Rect::auto(),
1180 margin: Rect::zero(),
1181 padding: Rect::zero(),
1182 border: Rect::zero(),
1183 gap: Size::zero(),
1184 #[cfg(feature = "block_layout")]
1185 text_align: Default::default(),
1186 #[cfg(feature = "flexbox")]
1187 flex_grow: 0.0,
1188 #[cfg(feature = "flexbox")]
1189 flex_shrink: 1.0,
1190 #[cfg(feature = "flexbox")]
1191 flex_basis: super::Dimension::AUTO,
1192 size: Size::auto(),
1193 min_size: Size::auto(),
1194 max_size: Size::auto(),
1195 aspect_ratio: Default::default(),
1196 #[cfg(feature = "grid")]
1197 grid_template_rows: Default::default(),
1198 #[cfg(feature = "grid")]
1199 grid_template_columns: Default::default(),
1200 #[cfg(feature = "grid")]
1201 grid_template_row_names: Default::default(),
1202 #[cfg(feature = "grid")]
1203 grid_template_column_names: Default::default(),
1204 #[cfg(feature = "grid")]
1205 grid_template_areas: Default::default(),
1206 #[cfg(feature = "grid")]
1207 grid_auto_rows: Default::default(),
1208 #[cfg(feature = "grid")]
1209 grid_auto_columns: Default::default(),
1210 #[cfg(feature = "grid")]
1211 grid_auto_flow: Default::default(),
1212 #[cfg(feature = "grid")]
1213 grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
1214 #[cfg(feature = "grid")]
1215 grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
1216 };
1217
1218 assert_eq!(Style::DEFAULT, Style::<DefaultCheapStr>::default());
1219 assert_eq!(Style::DEFAULT, old_defaults);
1220 }
1221
1222 // NOTE: Please feel free the update the sizes in this test as required. This test is here to prevent unintentional size changes
1223 // and to serve as accurate up-to-date documentation on the sizes.
1224 #[test]
1225 fn style_sizes() {
1226 use super::*;
1227 type S = crate::sys::DefaultCheapStr;
1228
1229 fn assert_type_size<T>(expected_size: usize) {
1230 let name = ::core::any::type_name::<T>();
1231 let name = name.replace("taffy::geometry::", "");
1232 let name = name.replace("taffy::style::dimension::", "");
1233 let name = name.replace("taffy::style::alignment::", "");
1234 let name = name.replace("taffy::style::flex::", "");
1235 let name = name.replace("taffy::style::grid::", "");
1236
1237 assert_eq!(
1238 ::core::mem::size_of::<T>(),
1239 expected_size,
1240 "Expected {} for be {} byte(s) but it was {} byte(s)",
1241 name,
1242 expected_size,
1243 ::core::mem::size_of::<T>(),
1244 );
1245 }
1246
1247 // Display and Position
1248 assert_type_size::<Display>(1);
1249 assert_type_size::<BoxSizing>(1);
1250 assert_type_size::<Position>(1);
1251 assert_type_size::<Overflow>(1);
1252
1253 // Dimensions and aggregations of Dimensions
1254 assert_type_size::<f32>(4);
1255 assert_type_size::<LengthPercentage>(8);
1256 assert_type_size::<LengthPercentageAuto>(8);
1257 assert_type_size::<Dimension>(8);
1258 assert_type_size::<Size<LengthPercentage>>(16);
1259 assert_type_size::<Size<LengthPercentageAuto>>(16);
1260 assert_type_size::<Size<Dimension>>(16);
1261 assert_type_size::<Rect<LengthPercentage>>(32);
1262 assert_type_size::<Rect<LengthPercentageAuto>>(32);
1263 assert_type_size::<Rect<Dimension>>(32);
1264
1265 // Alignment
1266 assert_type_size::<AlignContent>(1);
1267 assert_type_size::<AlignItems>(1);
1268 assert_type_size::<Option<AlignItems>>(1);
1269
1270 // Flexbox Container
1271 assert_type_size::<FlexDirection>(1);
1272 assert_type_size::<FlexWrap>(1);
1273
1274 // CSS Grid Container
1275 assert_type_size::<GridAutoFlow>(1);
1276 assert_type_size::<MinTrackSizingFunction>(8);
1277 assert_type_size::<MaxTrackSizingFunction>(8);
1278 assert_type_size::<TrackSizingFunction>(16);
1279 assert_type_size::<Vec<TrackSizingFunction>>(24);
1280 assert_type_size::<Vec<GridTemplateComponent<S>>>(24);
1281
1282 // String-type dependent (String)
1283 assert_type_size::<GridTemplateComponent<String>>(56);
1284 assert_type_size::<GridPlacement<String>>(32);
1285 assert_type_size::<Line<GridPlacement<String>>>(64);
1286 assert_type_size::<Style<String>>(536);
1287
1288 // String-type dependent (Arc<str>)
1289 assert_type_size::<GridTemplateComponent<Arc<str>>>(56);
1290 assert_type_size::<GridPlacement<Arc<str>>>(24);
1291 assert_type_size::<Line<GridPlacement<Arc<str>>>>(48);
1292 assert_type_size::<Style<Arc<str>>>(504);
1293 }
1294}