sql_cli/
column_manager.rs1use serde_json::Value;
2
3pub struct ColumnManager;
5
6impl ColumnManager {
7 #[must_use]
9 pub fn calculate_optimal_widths(data: &[Value]) -> Vec<u16> {
10 if data.is_empty() {
11 return Vec::new();
12 }
13
14 let first_row = match data.first() {
15 Some(row) => row,
16 None => return Vec::new(),
17 };
18
19 let obj = match first_row.as_object() {
20 Some(obj) => obj,
21 None => return Vec::new(),
22 };
23
24 let headers: Vec<&str> = obj.keys().map(std::string::String::as_str).collect();
25 let mut widths = Vec::new();
26
27 const MAX_ROWS_TO_CHECK: usize = 100;
29 let total_rows = data.len();
30
31 let rows_to_check: Vec<usize> = if total_rows <= MAX_ROWS_TO_CHECK {
33 (0..total_rows).collect()
35 } else {
36 let step = total_rows / MAX_ROWS_TO_CHECK;
38 (0..MAX_ROWS_TO_CHECK)
39 .map(|i| (i * step).min(total_rows - 1))
40 .collect()
41 };
42
43 for header in &headers {
44 let mut max_width = header.len();
46
47 for &row_idx in &rows_to_check {
49 if let Some(row) = data.get(row_idx) {
50 if let Some(obj) = row.as_object() {
51 if let Some(value) = obj.get(*header) {
52 let display_len = match value {
53 Value::String(s) => s.len(),
54 Value::Number(n) => n.to_string().len(),
55 Value::Bool(b) => b.to_string().len(),
56 Value::Null => 4, _ => value.to_string().len(),
58 };
59 max_width = max_width.max(display_len);
60 }
61 }
62 }
63 }
64
65 let optimal_width = (max_width + 2).max(4).min(50); widths.push(optimal_width as u16);
68 }
69
70 widths
71 }
72
73 #[must_use]
75 pub fn calculate_widths_for_filtered(headers: &[String], data: &[Vec<String>]) -> Vec<u16> {
76 let mut widths = Vec::new();
77
78 const MAX_ROWS_TO_CHECK: usize = 100;
80 let total_rows = data.len();
81
82 let rows_to_check: Vec<usize> = if total_rows <= MAX_ROWS_TO_CHECK {
84 (0..total_rows).collect()
85 } else {
86 let step = total_rows / MAX_ROWS_TO_CHECK;
87 (0..MAX_ROWS_TO_CHECK)
88 .map(|i| (i * step).min(total_rows - 1))
89 .collect()
90 };
91
92 for (col_idx, header) in headers.iter().enumerate() {
93 let mut max_width = header.len();
95
96 for &row_idx in &rows_to_check {
98 if let Some(row) = data.get(row_idx) {
99 if let Some(value) = row.get(col_idx) {
100 max_width = max_width.max(value.len());
101 }
102 }
103 }
104
105 let optimal_width = (max_width + 2).max(4).min(50);
107 widths.push(optimal_width as u16);
108 }
109
110 widths
111 }
112
113 #[must_use]
115 pub fn get_value_display_width(value: &Value) -> usize {
116 match value {
117 Value::String(s) => s.len(),
118 Value::Number(n) => n.to_string().len(),
119 Value::Bool(b) => b.to_string().len(),
120 Value::Null => 4, _ => value.to_string().len(),
122 }
123 }
124}