+use std::fs::File;
+use std::path::PathBuf;
+use std::io::Read;
+use std::time::{SystemTime, UNIX_EPOCH};
+
+pub struct Metadata {
+ pub id: String,
+ pub created_on: u128
+}
+
+impl Metadata {
+ pub fn serialize(&self) -> String {
+ format!(r#"{{\n "id": "{}",\n "created_on": {}\n}}"#, self.id, self.created_on)
+ }
+
+ pub fn deserialize(input: &str) -> Option<Metadata> {
+ let clean_input = input
+ .chars()
+ .filter(|c| !c.is_whitespace())
+ .collect::<String>();
+
+ let id = Metadata::read_field(&clean_input, "id")?;
+ let created_on = Metadata::read_field(&clean_input, "createdOn")
+ .or_else(|| Metadata::read_field(&clean_input, "created_on"))?;
+
+ Some(Metadata {
+ id,
+ created_on: created_on.parse().ok()?
+ })
+ }
+
+ pub fn read_or_create(file_path: &PathBuf) -> Metadata {
+ match Metadata::read_metadata_file(file_path) {
+ Some(metadata) => metadata,
+ None => {
+ let timestamp = SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .map(|duration| duration.as_millis() as u128)
+ .unwrap_or_else(|_| 0);
+ return Metadata {
+ id: timestamp.to_string(),
+ created_on: timestamp
+ }
+ }
+ }
+ }
+
+ fn read_metadata_file(file_path: &PathBuf) -> Option<Metadata> {
+ let mut file = File::open(file_path).ok()?;
+ let mut contents = String::new();
+ file.read_to_string(&mut contents).ok()?;
+ Metadata::deserialize(&contents)
+ }
+
+
+ fn read_field(input: &str, field_name: &str) -> Option<String> {
+ let key_pattern = format!(r#""{}":""#, field_name);
+ input.find(&key_pattern)
+ .and_then(|start| {
+ let value_start = start + key_pattern.len();
+ let value_end = input[value_start..]
+ .find(|c: char| c == ',' || c == '}' || c == '\n')
+ .unwrap_or_else(|| input[value_start..].len()) + value_start;
+
+ let raw_value = &input[value_start..value_end];
+ let value = raw_value.trim_matches('"').to_string();
+ Some(value)
+ })
+ }
+}