ratatui_core/layout/
size.rs

1#![warn(missing_docs)]
2use core::fmt;
3
4use crate::layout::Rect;
5
6/// A simple size struct for representing dimensions in the terminal.
7///
8/// The width and height are stored as `u16` values and represent the number of columns and rows
9/// respectively. This is used throughout the layout system to represent dimensions of rectangular
10/// areas and other layout elements.
11///
12/// Size can be created from tuples, extracted from rectangular areas, or constructed directly.
13/// It's commonly used in conjunction with [`Position`](crate::layout::Position) to define
14/// rectangular areas.
15///
16/// # Construction
17///
18/// - [`new`](Self::new) - Create a new size from width and height
19/// - [`default`](Default::default) - Create with zero dimensions
20///
21/// # Conversion
22///
23/// - [`from((u16, u16))`](Self::from) - Create from `(u16, u16)` tuple
24/// - [`from(Rect)`](Self::from) - Create from [`Rect`] (uses width and height)
25/// - [`into((u16, u16))`] - Convert to `(u16, u16)` tuple
26///
27/// # Computation
28///
29/// - [`area`](Self::area) - Compute the total number of cells covered by the size
30///
31/// # Examples
32///
33/// ```rust
34/// use ratatui_core::layout::{Rect, Size};
35///
36/// let size = Size::new(80, 24);
37/// assert_eq!(size.area(), 1920);
38/// let size = Size::from((80, 24));
39/// let size = Size::from(Rect::new(0, 0, 80, 24));
40/// assert_eq!(size.area(), 1920);
41/// ```
42///
43/// For comprehensive layout documentation and examples, see the [`layout`](crate::layout) module.
44#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46pub struct Size {
47    /// The width in columns
48    pub width: u16,
49    /// The height in rows
50    pub height: u16,
51}
52
53impl Size {
54    /// A zero sized Size
55    pub const ZERO: Self = Self::new(0, 0);
56
57    /// The minimum possible Size
58    pub const MIN: Self = Self::ZERO;
59
60    /// The maximum possible Size
61    pub const MAX: Self = Self::new(u16::MAX, u16::MAX);
62
63    /// Create a new `Size` struct
64    pub const fn new(width: u16, height: u16) -> Self {
65        Self { width, height }
66    }
67
68    /// Compute the total area of the size as a `u32`.
69    ///
70    /// The multiplication uses `u32` to avoid overflow when the width and height are at their
71    /// `u16` maximum values.
72    pub const fn area(self) -> u32 {
73        self.width as u32 * self.height as u32
74    }
75}
76
77impl From<(u16, u16)> for Size {
78    fn from((width, height): (u16, u16)) -> Self {
79        Self { width, height }
80    }
81}
82
83impl From<Size> for (u16, u16) {
84    fn from(size: Size) -> Self {
85        (size.width, size.height)
86    }
87}
88
89impl From<Rect> for Size {
90    fn from(rect: Rect) -> Self {
91        rect.as_size()
92    }
93}
94
95impl fmt::Display for Size {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        write!(f, "{}x{}", self.width, self.height)
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use alloc::string::ToString;
104
105    use super::*;
106
107    #[test]
108    fn new() {
109        let size = Size::new(10, 20);
110        assert_eq!(size.width, 10);
111        assert_eq!(size.height, 20);
112    }
113
114    #[test]
115    fn from_tuple() {
116        let size = Size::from((10, 20));
117        assert_eq!(size.width, 10);
118        assert_eq!(size.height, 20);
119    }
120
121    #[test]
122    fn to_tuple() {
123        let size = Size::from((10, 20));
124        let (width, height) = size.into();
125        assert_eq!(size.width, width);
126        assert_eq!(size.height, height);
127    }
128
129    #[test]
130    fn from_rect() {
131        let size = Size::from(Rect::new(0, 0, 10, 20));
132        assert_eq!(size.width, 10);
133        assert_eq!(size.height, 20);
134    }
135
136    #[test]
137    fn display() {
138        assert_eq!(Size::new(10, 20).to_string(), "10x20");
139    }
140
141    #[test]
142    fn area() {
143        assert_eq!(Size::new(10, 20).area(), 200);
144        assert_eq!(Size::new(0, 0).area(), 0);
145        assert_eq!(Size::new(u16::MAX, u16::MAX).area(), 4_294_836_225_u32);
146    }
147}