Skip to main content

alun_utils/
export.rs

1//! 导出导入工具:CSV / Excel / JSON
2//!
3//! 使用方式简洁,一行代码完成导入导出。
4
5use alun_core::{Result, Error};
6use serde::{Serialize, de::DeserializeOwned};
7
8/// 导出格式
9pub enum ExportFormat {
10    Csv,
11    Json,
12    Xlsx,
13}
14
15/// 导出工具
16pub struct Export;
17
18impl Export {
19    /// 将 KV 数据集导出为 CSV 字符串
20    ///
21    /// `columns` 指定列顺序,`rows` 为 key→value 映射的集合。
22    ///
23    /// ```ignore
24    /// let csv = Export::to_csv(&["id", "name"], &records)?;
25    /// ```
26    pub fn to_csv(
27        columns: &[&str],
28        rows: &[std::collections::HashMap<String, String>],
29    ) -> Result<String> {
30        let mut w = csv::Writer::from_writer(Vec::new());
31        w.write_record(columns).map_err(|e| Error::Msg(format!("CSV写入失败: {}", e)))?;
32        for row in rows {
33            let vals: Vec<&str> = columns.iter()
34                .map(|c| row.get(*c).map(|s| s.as_str()).unwrap_or(""))
35                .collect();
36            w.write_record(&vals).map_err(|e| Error::Msg(format!("CSV写入失败: {}", e)))?;
37        }
38        let data = w.into_inner().map_err(|e| Error::Msg(format!("CSV输出失败: {}", e)))?;
39        String::from_utf8(data).map_err(|e| Error::Msg(format!("UTF8转换失败: {}", e)))
40    }
41
42    /// 将结构化数据导出为 JSON
43    pub fn to_json<T: Serialize>(items: &[T]) -> Result<String> {
44        serde_json::to_string_pretty(items).map_err(|e| Error::Msg(format!("JSON序列化失败: {}", e)))
45    }
46
47    /// 导出为 XLSX 格式(BOM + CSV),兼容 Excel 打开
48    pub fn to_xlsx(
49        columns: &[&str],
50        rows: &[std::collections::HashMap<String, String>],
51    ) -> Result<Vec<u8>> {
52        let csv_content = Self::to_csv(columns, rows)?;
53        let bom = vec![0xEFu8, 0xBB, 0xBF];
54        let mut data = bom;
55        data.extend(csv_content.as_bytes());
56        Ok(data)
57    }
58}
59
60/// 导入工具
61pub struct Import;
62
63impl Import {
64    /// 从 CSV 字符串解析为 Vec<HashMap<String, String>>
65    pub fn from_csv(csv_str: &str) -> Result<Vec<std::collections::HashMap<String, String>>> {
66        let mut reader = csv::Reader::from_reader(csv_str.as_bytes());
67        let headers = reader.headers()
68            .map_err(|e| Error::Msg(format!("CSV头解析失败: {}", e)))?
69            .clone();
70        let mut rows = Vec::new();
71        for result in reader.records() {
72            let record = result.map_err(|e| Error::Msg(format!("CSV行解析失败: {}", e)))?;
73            let mut map = std::collections::HashMap::new();
74            for (i, val) in record.iter().enumerate() {
75                if let Some(h) = headers.get(i) { map.insert(h.to_string(), val.to_string()); }
76            }
77            rows.push(map);
78        }
79        Ok(rows)
80    }
81
82    /// 从 JSON 反序列化
83    pub fn from_json<T: DeserializeOwned>(json_str: &str) -> Result<Vec<T>> {
84        serde_json::from_str(json_str).map_err(|e| Error::Msg(format!("JSON解析失败: {}", e)))
85    }
86}