Split csv module

This commit is contained in:
fluo10 2025-04-30 08:34:01 +09:00
parent d90fb5c7fe
commit 25e80f74a8
5 changed files with 80 additions and 54 deletions

View file

@ -1,53 +1,29 @@
mod reader;
mod record;
mod table;
mod writer;
pub use reader::CsvReader;
pub use record::CsvRecord;
pub use table::CsvTable;
pub use writer::CsvWriter;
use crate::error::Error;
use chrono::{DateTime, NaiveDateTime};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CsvRecord{
pub timestamp: NaiveDateTime,
#[serde(with = "string_to_escape")]
pub comment: String,
pub tag: String,
pub count: i32,
}
pub mod string_to_escape {
use serde::{Deserialize, Deserializer, Serializer};
pub fn deserialize<'de, D>(d: D) -> Result<String, D::Error>
where D: Deserializer<'de>
{
Ok(String::deserialize(d)?
.replace("\\n", "\n")
.replace("\\t", "\t")
.replace("\\\"", "\"")
.replace("\\\\", "\\")
)
}
pub fn serialize<S>(s: &str, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_str(&s
.replace("\n", "\\n")
.replace("\t", "\\t")
.replace("\"", "\\\"")
.replace("\\", "\\\\")
)
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use chrono::{NaiveDate, NaiveTime};
const RECORD_CSV:&str = r#"timestamp,comment,tag,count
2025-05-01T12:34:56,test\ntest,test,1"#;
2025-05-01T12:34:56,"test
test",test,1
"#;
fn get_record_struct() -> Vec<CsvRecord>{
fn get_records() -> Vec<CsvRecord>{
vec![CsvRecord {
timestamp: NaiveDate::from_ymd_opt(2025, 5, 1)
.unwrap().and_hms_micro_opt(12, 34, 56, 0).unwrap(),
@ -58,16 +34,6 @@ test".to_owned(),
}]
}
#[test]
fn serialize_string() {
}
#[test]
fn deserialize_string() {
}
#[test]
fn deserialize_record() {
println!("{:?}", RECORD_CSV);
@ -84,14 +50,18 @@ test".to_owned(),
let record: CsvRecord = raw_record.deserialize(Some(&headers)).unwrap();
records.push(record);
}
assert_eq!(records, get_record_struct());
assert_eq!(records, get_records());
}
#[test]
fn serialize_record() {
todo!()
let buf : Vec<u8> = Vec::new();
let mut wtr = csv::Writer::from_writer(buf);
for record in get_records().into_iter() {
wtr.serialize(record).unwrap();
}
wtr.flush().unwrap();
assert_eq!(RECORD_CSV, &String::from_utf8(wtr.into_inner().unwrap()).unwrap())
}
}

View file

@ -0,0 +1,9 @@
pub struct CsvReader<T> {
inner: T,
}
impl<T> CsvReader<T> {
pub fn into_inner(self) -> T {
self.inner
}
}

View file

@ -0,0 +1,19 @@
use chrono::{DateTime, NaiveDateTime};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CsvRecord{
pub timestamp: NaiveDateTime,
pub comment: String,
pub tag: String,
pub count: i32,
}
impl TryFrom<crate::entity::RecordDetailModel> for CsvRecord{
type Error = crate::error::Error;
fn try_from(model: crate::entity::RecordDetailModel) -> Result<Self, Self::Error> {
todo!()
}
}

View file

@ -0,0 +1,19 @@
use crate::error::Error;
use super::CsvRecord;
pub struct CsvTable{
inner: Vec<CsvRecord>
}
impl CsvTable {
pub fn into_inner(self) -> Vec<CsvRecord> {
self.inner
}
}
impl From<Vec<CsvRecord>> for CsvTable {
fn from(v: Vec<CsvRecord>) -> Self {
Self {
inner: v,
}
}
}

View file

@ -0,0 +1,9 @@
pub struct CsvWriter<T> {
inner: T
}
impl<T> CsvWriter<T> {
pub fn into_inner(self) -> T {
self.inner
}
}