]>
Commit | Line | Data |
---|---|---|
1 | use std::fs::File; | |
2 | use std::path::PathBuf; | |
3 | use std::io::Read; | |
4 | use std::time::{SystemTime, UNIX_EPOCH}; | |
5 | ||
6 | pub struct Metadata { | |
7 | pub id: String, | |
8 | pub created_on: u128 | |
9 | } | |
10 | ||
11 | impl Metadata { | |
12 | pub fn serialize(&self) -> String { | |
13 | format!(r#"{{\n "id": "{}",\n "created_on": {}\n}}"#, self.id, self.created_on) | |
14 | } | |
15 | ||
16 | pub fn deserialize(input: &str) -> Option<Metadata> { | |
17 | let clean_input = input | |
18 | .chars() | |
19 | .filter(|c| !c.is_whitespace()) | |
20 | .collect::<String>(); | |
21 | ||
22 | let id = Metadata::read_field(&clean_input, "id")?; | |
23 | let created_on = Metadata::read_field(&clean_input, "createdOn") | |
24 | .or_else(|| Metadata::read_field(&clean_input, "created_on"))?; | |
25 | ||
26 | Some(Metadata { | |
27 | id, | |
28 | created_on: created_on.parse().ok()? | |
29 | }) | |
30 | } | |
31 | ||
32 | pub fn read_or_create(file_path: &PathBuf) -> Metadata { | |
33 | match Metadata::read_metadata_file(file_path) { | |
34 | Some(metadata) => metadata, | |
35 | None => { | |
36 | let timestamp = SystemTime::now() | |
37 | .duration_since(UNIX_EPOCH) | |
38 | .map(|duration| duration.as_millis() as u128) | |
39 | .unwrap_or_else(|_| 0); | |
40 | return Metadata { | |
41 | id: timestamp.to_string(), | |
42 | created_on: timestamp | |
43 | } | |
44 | } | |
45 | } | |
46 | } | |
47 | ||
48 | fn read_metadata_file(file_path: &PathBuf) -> Option<Metadata> { | |
49 | let mut file = File::open(file_path).ok()?; | |
50 | let mut contents = String::new(); | |
51 | file.read_to_string(&mut contents).ok()?; | |
52 | Metadata::deserialize(&contents) | |
53 | } | |
54 | ||
55 | ||
56 | fn read_field(input: &str, field_name: &str) -> Option<String> { | |
57 | let key_pattern = format!(r#""{}":""#, field_name); | |
58 | input.find(&key_pattern) | |
59 | .and_then(|start| { | |
60 | let value_start = start + key_pattern.len(); | |
61 | let value_end = input[value_start..] | |
62 | .find(|c: char| c == ',' || c == '}' || c == '\n') | |
63 | .unwrap_or_else(|| input[value_start..].len()) + value_start; | |
64 | ||
65 | let raw_value = &input[value_start..value_end]; | |
66 | let value = raw_value.trim_matches('"').to_string(); | |
67 | Some(value) | |
68 | }) | |
69 | } | |
70 | } |