rskit_process/pty/
size.rs1use std::os::unix::io::AsRawFd;
4
5#[derive(Debug, Clone, Copy, Eq, PartialEq)]
12pub struct PtySize {
13 pub rows: u16,
15 pub cols: u16,
17 pub pixel_width: u16,
19 pub pixel_height: u16,
21}
22
23impl Default for PtySize {
24 fn default() -> Self {
26 Self {
27 rows: 24,
28 cols: 80,
29 pixel_width: 0,
30 pixel_height: 0,
31 }
32 }
33}
34
35impl PtySize {
36 #[must_use]
38 pub const fn new(rows: u16, cols: u16) -> Self {
39 Self {
40 rows,
41 cols,
42 pixel_width: 0,
43 pixel_height: 0,
44 }
45 }
46
47 pub(crate) const fn to_winsize(self) -> libc::winsize {
49 libc::winsize {
50 ws_row: self.rows,
51 ws_col: self.cols,
52 ws_xpixel: self.pixel_width,
53 ws_ypixel: self.pixel_height,
54 }
55 }
56}
57
58#[must_use]
64pub fn terminal_size(fd: &impl AsRawFd) -> Option<PtySize> {
65 let mut winsize: libc::winsize = unsafe { std::mem::zeroed() };
68 let result = unsafe { libc::ioctl(fd.as_raw_fd(), libc::TIOCGWINSZ, &raw mut winsize) };
72 if result != 0 {
73 return None;
74 }
75 Some(PtySize {
76 rows: winsize.ws_row,
77 cols: winsize.ws_col,
78 pixel_width: winsize.ws_xpixel,
79 pixel_height: winsize.ws_ypixel,
80 })
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn default_is_eighty_by_twenty_four() {
89 let size = PtySize::default();
90 assert_eq!(size.cols, 80);
91 assert_eq!(size.rows, 24);
92 assert_eq!(size.pixel_width, 0);
93 assert_eq!(size.pixel_height, 0);
94 }
95
96 #[test]
97 fn new_sets_rows_and_cols_only() {
98 let size = PtySize::new(40, 120);
99 assert_eq!(size.rows, 40);
100 assert_eq!(size.cols, 120);
101 assert_eq!(size.pixel_width, 0);
102 }
103
104 #[test]
105 fn winsize_round_trips_dimensions() {
106 let winsize = PtySize {
107 rows: 10,
108 cols: 20,
109 pixel_width: 30,
110 pixel_height: 40,
111 }
112 .to_winsize();
113 assert_eq!(winsize.ws_row, 10);
114 assert_eq!(winsize.ws_col, 20);
115 assert_eq!(winsize.ws_xpixel, 30);
116 assert_eq!(winsize.ws_ypixel, 40);
117 }
118
119 #[test]
120 fn non_terminal_fd_has_no_size() {
121 let (reader, _writer) = std::io::pipe().expect("pipe");
123 assert!(terminal_size(&reader).is_none());
124 }
125}