Skip to main content

taffy/style/
mod.rs

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