Skip to main content

xls_rs/operations/
types.rs

1//! Type definitions for operations
2
3use anyhow::Result;
4
5/// Progress callback for long-running operations
6pub trait ProgressCallback: Send {
7    fn on_progress(&mut self, current: usize, total: Option<usize>, message: &str);
8}
9
10/// Simple progress reporter that prints to stderr
11pub struct StderrProgress {
12    last_percent: usize,
13}
14
15impl StderrProgress {
16    pub fn new() -> Self {
17        Self { last_percent: 0 }
18    }
19}
20
21impl ProgressCallback for StderrProgress {
22    fn on_progress(&mut self, current: usize, total: Option<usize>, message: &str) {
23        if let Some(total) = total {
24            let percent = if total > 0 {
25                (current * 100) / total
26            } else {
27                0
28            };
29            if percent != self.last_percent {
30                eprintln!("\r{}: {}% ({}/{})", message, percent, current, total);
31                self.last_percent = percent;
32            }
33        } else {
34            eprintln!("\r{}: {} processed", message, current);
35        }
36    }
37}
38
39/// No-op progress callback
40pub struct NoProgress;
41
42impl ProgressCallback for NoProgress {
43    fn on_progress(&mut self, _current: usize, _total: Option<usize>, _message: &str) {}
44}
45
46/// Sort order
47#[derive(Debug, Clone, Copy, PartialEq)]
48pub enum SortOrder {
49    Ascending,
50    Descending,
51}
52
53/// Join type for merge operations
54#[derive(Debug, Clone, Copy, PartialEq)]
55pub enum JoinType {
56    Inner,
57    Left,
58    Right,
59    Outer,
60}
61
62impl JoinType {
63    pub fn from_str(s: &str) -> Result<Self> {
64        match s.to_lowercase().as_str() {
65            "inner" => Ok(JoinType::Inner),
66            "left" => Ok(JoinType::Left),
67            "right" => Ok(JoinType::Right),
68            "outer" | "full" => Ok(JoinType::Outer),
69            _ => anyhow::bail!("Unknown join type: {}. Use: inner, left, right, outer", s),
70        }
71    }
72}
73
74/// Aggregation functions for groupby
75#[derive(Debug, Clone, Copy)]
76pub enum AggFunc {
77    Sum,
78    Count,
79    Mean,
80    Min,
81    Max,
82}
83
84impl AggFunc {
85    pub fn from_str(s: &str) -> Result<Self> {
86        match s.to_lowercase().as_str() {
87            "sum" => Ok(AggFunc::Sum),
88            "count" => Ok(AggFunc::Count),
89            "mean" | "avg" | "average" => Ok(AggFunc::Mean),
90            "min" => Ok(AggFunc::Min),
91            "max" => Ok(AggFunc::Max),
92            _ => anyhow::bail!(
93                "Unknown aggregation: {}. Use: sum, count, mean, min, max",
94                s
95            ),
96        }
97    }
98
99    pub fn name(&self) -> &'static str {
100        match self {
101            AggFunc::Sum => "sum",
102            AggFunc::Count => "count",
103            AggFunc::Mean => "mean",
104            AggFunc::Min => "min",
105            AggFunc::Max => "max",
106        }
107    }
108
109    pub fn apply(&self, values: &[f64]) -> f64 {
110        if values.is_empty() {
111            return 0.0;
112        }
113        match self {
114            AggFunc::Sum => values.iter().sum(),
115            AggFunc::Count => values.len() as f64,
116            AggFunc::Mean => values.iter().sum::<f64>() / values.len() as f64,
117            AggFunc::Min => values.iter().cloned().fold(f64::INFINITY, f64::min),
118            AggFunc::Max => values.iter().cloned().fold(f64::NEG_INFINITY, f64::max),
119        }
120    }
121}