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