kobo_db_tools/export/
bookmark.rs1use super::{error::ExportError, Export};
2use crate::model::Bookmark;
3use chrono::{DateTime, Utc};
4use csv::Writer;
5use std::io::Write;
6use std::str::FromStr;
7use serde_json;
8
9impl Export for [Bookmark] {
10 fn to_csv(&self) -> Result<String, ExportError> {
11 let mut wtr = Writer::from_writer(vec![]);
12 for bookmark in self {
13 wtr.serialize(bookmark)?;
14 }
15 Ok(String::from_utf8(wtr.into_inner()?)?)
16 }
17
18 fn to_md(&self) -> Result<String, ExportError> {
19 let mut buffer = Vec::new();
20 for bookmark in self {
21 writeln!(buffer, "### {}", bookmark.book_title)?;
22 writeln!(buffer, "\n> {}", bookmark.content)?;
23 writeln!(
24 buffer,
25 "\n**Chapter Progress:** {:.2}%",
26 bookmark.chapter_progress * 100.0
27 )?;
28 let formatted_date = DateTime::<Utc>::from_str(&bookmark.create_date)
29 .map(|dt| dt.format("%Y-%m-%d %H:%M:%S UTC").to_string())
30 .unwrap_or_else(|_| bookmark.create_date.clone());
31 writeln!(buffer, "**Created:** {}", formatted_date)?;
32 writeln!(buffer, "\n---\n")?;
33 }
34 Ok(String::from_utf8(buffer)?)
35 }
36
37 fn to_json(&self) -> Result<String, ExportError> {
38 serde_json::to_string(self).map_err(ExportError::JsonToString)
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::model::Bookmark;
46
47 #[test]
48 fn test_to_csv() {
49 let bookmarks = vec![
50 Bookmark {
51 content_id: "content1".to_string(),
52 content: "content text".to_string(),
53 book_id: "book1".to_string(),
54 book_title: "Book Title".to_string(),
55 color: 1,
56 chapter_progress: 0.5,
57 create_date: "2025-07-05T10:00:00Z".to_string(),
58 write_date: "2025-07-05T10:00:00Z".to_string(),
59 },
60 ];
61
62 let expected_csv = "content_id,content,book_id,book_title,color,chapter_progress,create_date,write_date\ncontent1,content text,book1,Book Title,1,0.5,2025-07-05T10:00:00Z,2025-07-05T10:00:00Z\n".to_string();
63 let result = bookmarks.to_csv().unwrap();
64 assert_eq!(result, expected_csv);
65 }
66
67 #[test]
68 fn test_to_json() {
69 let bookmarks = vec![
70 Bookmark {
71 content_id: "content1".to_string(),
72 content: "content text".to_string(),
73 book_id: "book1".to_string(),
74 book_title: "Book Title".to_string(),
75 color: 1,
76 chapter_progress: 0.5,
77 create_date: "2025-07-05T10:00:00Z".to_string(),
78 write_date: "2025-07-05T10:00:00Z".to_string(),
79 },
80 ];
81
82 let expected_json = serde_json::to_string(&bookmarks).unwrap();
83 let result = bookmarks.to_json().unwrap();
84 assert_eq!(result, expected_json);
85 }
86}