about summary refs log tree commit diff
path: root/converge/src/timedb.rs
diff options
context:
space:
mode:
Diffstat (limited to 'converge/src/timedb.rs')
-rwxr-xr-xconverge/src/timedb.rs97
1 files changed, 97 insertions, 0 deletions
diff --git a/converge/src/timedb.rs b/converge/src/timedb.rs
new file mode 100755
index 0000000..718115d
--- /dev/null
+++ b/converge/src/timedb.rs
@@ -0,0 +1,97 @@
+use std::path::Path;
+
+use time::OffsetDateTime;
+
+#[derive(Debug)]
+pub struct TimeDb {
+	data: Vec<TimedFile>,
+}
+
+impl TimeDb {
+	pub fn load<P: AsRef<Path>>(path: P) -> Self {
+		let file = std::fs::read_to_string(path).unwrap();
+
+		let mut data = vec![];
+		for line in file.lines() {
+			let it = TimedFile::parse_line(line);
+			data.push(it);
+		}
+
+		Self { data }
+	}
+
+	pub fn get_times(&self, path: &str) -> Option<&TimedFile> {
+		for file in &self.data {
+			if &file.path == path {
+				return Some(file);
+			}
+		}
+
+		None
+	}
+}
+
+#[derive(Debug)]
+pub struct TimedFile {
+	path: String,
+	pub creation: Option<OffsetDateTime>,
+	pub modification: Option<OffsetDateTime>,
+	pub access: Option<OffsetDateTime>,
+}
+
+impl TimedFile {
+	pub fn parse_line<S: AsRef<str>>(raw: S) -> Self {
+		let mut values = raw.as_ref().rsplitn(4, ",").collect::<Vec<&str>>();
+		values.reverse();
+
+		let to_odt = |str: &&str| -> Option<OffsetDateTime> {
+			str.parse::<u64>()
+				.ok()
+				.map(|t| OffsetDateTime::from_unix_timestamp(t as i64).unwrap())
+		};
+
+		let path = unescape(values[0]);
+		let creation = values.get(1).map(to_odt).flatten();
+		let modification = values.get(2).map(to_odt).flatten();
+		let access = values.get(3).map(to_odt).flatten();
+
+		Self {
+			path,
+			creation,
+			modification,
+			access,
+		}
+	}
+}
+
+// Permissive unescape. Everything that's not \\ or \, is passed
+// unchanged, while those get their slash removed
+fn unescape<S: AsRef<str>>(raw: S) -> String {
+	let raw = raw.as_ref();
+
+	if !raw.contains('\\') {
+		return raw.to_owned();
+	}
+
+	let mut unescape = String::with_capacity(raw.len());
+	let mut escaped = false;
+	for ch in raw.chars() {
+		match (escaped, ch) {
+			(false, '\\') => {
+				escaped = true;
+			}
+			(false, c) => unescape.push(c),
+			(true, '\\') | (true, ',') => {
+				unescape.push(ch);
+				escaped = false;
+			}
+			(true, c) => {
+				unescape.push('\\');
+				unescape.push(c);
+				escaped = false;
+			}
+		}
+	}
+
+	unescape
+}