Skip to main content

xls_rs/
handler_registry.rs

1//! Handler registry for unified file format handling (DRY, KISS, SOC)
2
3use crate::columnar::{AvroHandler, ParquetHandler};
4use crate::csv_handler::CsvHandler;
5use crate::excel::ExcelHandler;
6use crate::format_detector::DefaultFormatDetector;
7use crate::google_sheets::GoogleSheetsHandler;
8use crate::traits::FormatDetector;
9use crate::traits::{DataReader, DataWriteOptions, DataWriter, FileHandler};
10use anyhow::Result;
11
12/// Registry that manages file handlers by format
13pub struct HandlerRegistry {
14    format_detector: DefaultFormatDetector,
15}
16
17impl HandlerRegistry {
18    pub fn new() -> Self {
19        Self {
20            format_detector: DefaultFormatDetector::new(),
21        }
22    }
23
24    /// Get a handler for reading a file based on its format
25    pub fn get_reader(&self, path: &str) -> Result<Box<dyn DataReader>> {
26        let format = self.format_detector.detect_format(path)?;
27
28        match format.as_str() {
29            "csv" => Ok(Box::new(CsvHandler::new())),
30            "xlsx" | "xls" | "ods" => Ok(Box::new(ExcelHandler::new())),
31            "parquet" => Ok(Box::new(ParquetHandler::new())),
32            "avro" => Ok(Box::new(AvroHandler::new())),
33            "gsheet" => Ok(Box::new(GoogleSheetsHandler::new())),
34            _ => anyhow::bail!("Unsupported format: {format}"),
35        }
36    }
37
38    /// Get a handler for writing a file based on its format
39    pub fn get_writer(&self, path: &str) -> Result<Box<dyn DataWriter>> {
40        let format = self.format_detector.detect_format(path)?;
41
42        match format.as_str() {
43            "csv" => Ok(Box::new(CsvHandler::new())),
44            "xlsx" | "xls" | "ods" => Ok(Box::new(ExcelHandler::new())),
45            "parquet" => Ok(Box::new(ParquetHandler::new())),
46            "avro" => Ok(Box::new(AvroHandler::new())),
47            "gsheet" => Ok(Box::new(GoogleSheetsHandler::new())),
48            _ => anyhow::bail!("Unsupported format: {format}"),
49        }
50    }
51
52    /// Get a file handler (both read and write)
53    pub fn get_handler(&self, path: &str) -> Result<Box<dyn FileHandler>> {
54        let format = self.format_detector.detect_format(path)?;
55
56        match format.as_str() {
57            "csv" => Ok(Box::new(CsvHandler::new())),
58            "parquet" => Ok(Box::new(ParquetHandler::new())),
59            "avro" => Ok(Box::new(AvroHandler::new())),
60            "gsheet" => Ok(Box::new(GoogleSheetsHandler::new())),
61            _ => anyhow::bail!("Unsupported format: {format}"),
62        }
63    }
64
65    /// Read data from any supported format
66    pub fn read(&self, path: &str) -> Result<Vec<Vec<String>>> {
67        let reader = self.get_reader(path)?;
68        reader.read(path)
69    }
70
71    /// Write data to any supported format
72    pub fn write(&self, path: &str, data: &[Vec<String>], options: DataWriteOptions) -> Result<()> {
73        let writer = self.get_writer(path)?;
74        writer.write(path, data, options)
75    }
76}