From 85d67c9efd34a06581a973f6340263d5e19705a6 Mon Sep 17 00:00:00 2001 From: sigil-03 Date: Tue, 22 Jul 2025 22:52:06 -0600 Subject: [PATCH] add initial `Entry` code - single files work --- src/entry.rs | 151 ++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + test/entry/0000/author | 1 + test/entry/0000/creation_time | 1 + test/entry/0000/entry | 1 + test/entry/0000/id | 1 + test/entry/0001/author | 1 + test/entry/0001/creation_time | 1 + test/entry/0001/id | 1 + 9 files changed, 160 insertions(+) create mode 100644 src/entry.rs create mode 100644 test/entry/0000/author create mode 100644 test/entry/0000/creation_time create mode 100644 test/entry/0000/entry create mode 100644 test/entry/0000/id create mode 100644 test/entry/0001/author create mode 100644 test/entry/0001/creation_time create mode 100644 test/entry/0001/id diff --git a/src/entry.rs b/src/entry.rs new file mode 100644 index 0000000..51b495a --- /dev/null +++ b/src/entry.rs @@ -0,0 +1,151 @@ +use std::io::{Read, Write}; +use thiserror::Error; + +// TODO: i think this method of doing error handling probably has bad scoping +#[derive(Error, Debug)] +pub enum Error { + #[error(transparent)] + IoError(#[from] std::io::Error), + #[error(transparent)] + ParseError(#[from] chrono::ParseError), +} + +pub trait Enterable +where + Self: Sized, +{ + // load the type from a directory path + // TODO: return a result + fn fetch_from_fs(path: &std::path::Path) -> Result; + + // store self in the FS + // TODO: return a result + fn store_to_fs(self, path: &std::path::Path) -> Result<(), Error>; +} + +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct Entry { + pub id: String, + pub author: String, + pub creation_time: chrono::DateTime, + pub entry: T, +} + +impl Enterable for Entry { + fn fetch_from_fs(path: &std::path::Path) -> Result { + let id_file_path = path.join("id"); + let mut id_file = std::fs::File::open(&id_file_path)?; + let mut id_buffer = String::new(); + id_file.read_to_string(&mut id_buffer)?; + + // author + let author_file_path = path.join("author"); + let mut author_file = std::fs::File::open(&author_file_path)?; + let mut author_buffer = String::new(); + author_file.read_to_string(&mut author_buffer)?; + + // creation_time + let creation_time_file_path = path.join("creation_time"); + let mut creation_time_file = std::fs::File::open(&creation_time_file_path)?; + let mut creation_time_buffer = String::new(); + creation_time_file.read_to_string(&mut creation_time_buffer)?; + + let entry_file_path_buf = path.join("entry"); + let entry_file_path = entry_file_path_buf.as_path(); + + Ok(Self { + id: id_buffer, + author: author_buffer, + creation_time: chrono::DateTime::<_>::parse_from_rfc3339(&creation_time_buffer)?.into(), + entry: ::fetch_from_fs(entry_file_path)?, + }) + } + + fn store_to_fs(self, path: &std::path::Path) -> Result<(), Error> { + // id + let id_file_path = path.join("id"); + let mut id_file = std::fs::File::create(&id_file_path)?; + write!(id_file, "{}", self.id)?; + + // author + let author_file_path = path.join("author"); + let mut author_file = std::fs::File::create(&author_file_path)?; + write!(author_file, "{}", self.author)?; + + // created + let creation_time_file_path = path.join("creation_time"); + let mut creation_time_file = std::fs::File::create(&creation_time_file_path)?; + write!(creation_time_file, "{}", self.creation_time.to_rfc3339())?; + + // entry + // TODO: probably need to figure out better naming than "entry" + // TODO: fix this pathbuf nonsense woooooof + let entry_file_path_buf = path.join("entry"); + let entry_file_path = entry_file_path_buf.as_path(); + self.entry.store_to_fs(entry_file_path)?; + Ok(()) + } +} + +mod test { + + use super::*; + impl Enterable for String { + fn fetch_from_fs(path: &std::path::Path) -> Result { + let mut file = std::fs::File::open(&path)?; + let mut buffer = String::new(); + file.read_to_string(&mut buffer)?; + Ok(buffer) + } + fn store_to_fs(self, path: &std::path::Path) -> Result<(), Error> { + let mut file = std::fs::File::create(&path)?; + write!(file, "{}", self)?; + Ok(()) + } + } + + impl Enterable for Vec { + fn fetch_from_fs(path: &std::path::Path) -> Result { + todo!("implement this"); + } + fn store_to_fs(self, path: &std::path::Path) -> Result<(), Error> { + todo!("implement this"); + } + } + + #[test] + fn store_load_string_entry() { + let test_path = std::path::Path::new("./test/entry/0000"); + let entry = Entry:: { + id: String::from("87fa3146b90db61c4ea0de182798a0e5"), + author: String::from("test"), + creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-22T21:54:42-06:00") + .unwrap() + .with_timezone(&chrono::Local), + entry: String::from("entry string"), + }; + entry.clone().store_to_fs(test_path).unwrap(); + + let fs_entry = Entry::::fetch_from_fs(test_path).unwrap(); + + assert_eq!(entry, fs_entry); + } + + #[test] + fn store_load_vec_string_entry() { + let test_path = std::path::Path::new("./test/entry/0001"); + let entry = Entry::> { + id: String::from("87fa3146b90db61c4ea0de182798a0e5"), + author: String::from("test"), + creation_time: chrono::DateTime::parse_from_rfc3339("2025-07-22T21:54:42-06:00") + .unwrap() + .with_timezone(&chrono::Local), + entry: vec![String::from("string 1"), String::from("string 2")], + }; + entry.clone().store_to_fs(test_path).unwrap(); + + let fs_entry = Entry::>::fetch_from_fs(test_path).unwrap(); + + assert_eq!(entry, fs_entry); + } +} diff --git a/src/lib.rs b/src/lib.rs index b6245b9..740e431 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ pub mod git; pub mod issue; pub mod issues; +pub mod entry; + use crate::issue::State; #[derive(Debug, thiserror::Error)] diff --git a/test/entry/0000/author b/test/entry/0000/author new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/test/entry/0000/author @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/test/entry/0000/creation_time b/test/entry/0000/creation_time new file mode 100644 index 0000000..380d475 --- /dev/null +++ b/test/entry/0000/creation_time @@ -0,0 +1 @@ +2025-07-22T21:54:42-06:00 \ No newline at end of file diff --git a/test/entry/0000/entry b/test/entry/0000/entry new file mode 100644 index 0000000..5db03ab --- /dev/null +++ b/test/entry/0000/entry @@ -0,0 +1 @@ +entry string \ No newline at end of file diff --git a/test/entry/0000/id b/test/entry/0000/id new file mode 100644 index 0000000..b209563 --- /dev/null +++ b/test/entry/0000/id @@ -0,0 +1 @@ +87fa3146b90db61c4ea0de182798a0e5 \ No newline at end of file diff --git a/test/entry/0001/author b/test/entry/0001/author new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/test/entry/0001/author @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/test/entry/0001/creation_time b/test/entry/0001/creation_time new file mode 100644 index 0000000..380d475 --- /dev/null +++ b/test/entry/0001/creation_time @@ -0,0 +1 @@ +2025-07-22T21:54:42-06:00 \ No newline at end of file diff --git a/test/entry/0001/id b/test/entry/0001/id new file mode 100644 index 0000000..b209563 --- /dev/null +++ b/test/entry/0001/id @@ -0,0 +1 @@ +87fa3146b90db61c4ea0de182798a0e5 \ No newline at end of file