ailloli_ui_terminal_core/
size.rs

1//! Terminal grid dimensions in rows and columns.
2
3use serde::{Deserialize, Serialize};
4
5/// Terminal grid dimensions, measured in whole character cells.
6///
7/// [`Self::new`] guarantees both values are at least one. Public fields and
8/// derived deserialization can bypass that invariant; use [`Self::clamped`]
9/// before arithmetic/indexing. There is no upper bound.
10///
11/// # Examples
12///
13/// ```
14/// use ailloli_ui_terminal_core::TerminalSize;
15/// assert_eq!(TerminalSize::new(24, 80), TerminalSize { rows: 24, cols: 80 });
16/// ```
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
18pub struct TerminalSize {
19    /// Visible row count in cells.
20    pub rows: usize,
21    /// Visible column count in cells.
22    pub cols: usize,
23}
24
25impl TerminalSize {
26    /// Default terminal height: 24 rows.
27    ///
28    /// # Examples
29    ///
30    /// ```
31    /// use ailloli_ui_terminal_core::TerminalSize;
32    /// assert_eq!(TerminalSize::DEFAULT_ROWS, 24);
33    /// ```
34    pub const DEFAULT_ROWS: usize = 24;
35    /// Default terminal width: 80 columns.
36    ///
37    /// # Examples
38    ///
39    /// ```
40    /// use ailloli_ui_terminal_core::TerminalSize;
41    /// assert_eq!(TerminalSize::DEFAULT_COLS, 80);
42    /// ```
43    pub const DEFAULT_COLS: usize = 80;
44
45    /// Creates a size, replacing each zero dimension independently with one.
46    ///
47    /// All positive `usize` values, including [`usize::MAX`], are retained.
48    ///
49    /// # Examples
50    ///
51    /// ```
52    /// use ailloli_ui_terminal_core::TerminalSize;
53    /// assert_eq!(TerminalSize::new(0, 0), TerminalSize { rows: 1, cols: 1 });
54    /// ```
55    pub const fn new(rows: usize, cols: usize) -> Self {
56        Self {
57            rows: if rows == 0 { 1 } else { rows },
58            cols: if cols == 0 { 1 } else { cols },
59        }
60    }
61
62    /// Returns this size with zero dimensions replaced by one.
63    ///
64    /// # Examples
65    ///
66    /// ```
67    /// use ailloli_ui_terminal_core::TerminalSize;
68    /// assert_eq!(TerminalSize { rows: 0, cols: 7 }.clamped(), TerminalSize::new(1, 7));
69    /// ```
70    pub const fn clamped(self) -> Self {
71        Self::new(self.rows, self.cols)
72    }
73}
74
75impl Default for TerminalSize {
76    fn default() -> Self {
77        Self::new(Self::DEFAULT_ROWS, Self::DEFAULT_COLS)
78    }
79}