1use std::{fs, io, path::Path};
5
6use crate::error::{Error, Result};
7use serde::{Deserialize, Serialize};
8use serde_json::Value as JsonValue;
9use std::fmt::Debug;
10
11use crate::XvcEntity;
12
13use super::{sorted_files, timestamp};
14
15#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
17#[serde(bound = "T: Serialize, for<'lt> T: Deserialize<'lt>")]
18pub enum Event<T>
19where
20 T: Serialize + for<'lt> Deserialize<'lt> + Clone + Debug,
21{
22 Add {
24 entity: XvcEntity,
26 value: T,
28 },
29 Remove {
32 entity: XvcEntity,
35 },
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
40#[serde(bound = "T: Serialize, for<'lt> T: Deserialize<'lt>")]
41pub struct EventLog<T>(Vec<Event<T>>)
42where
43 T: Serialize + for<'lt> Deserialize<'lt> + Clone + Debug;
44
45impl<T> Default for EventLog<T>
46where
47 T: Serialize + for<'lt> Deserialize<'lt> + Clone + Debug,
48{
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54impl<T> EventLog<T>
55where
56 T: Serialize + for<'lt> Deserialize<'lt> + Clone + Debug,
57{
58 pub fn new() -> Self {
60 Self(Vec::new())
61 }
62
63 pub fn from_events(events: Vec<Event<T>>) -> Self {
65 Self(events)
66 }
67
68 pub fn to_json(&self) -> Result<JsonValue> {
71 serde_json::to_value(&self.0).map_err(|e| Error::JsonError { source: e }.warn())
72 }
73
74 pub fn from_json(json_str: &str) -> Result<Self> {
76 serde_json::from_str(json_str).map_err(|e| Error::JsonError { source: e }.warn())
77 }
78
79 pub fn from_file(path: &Path) -> Result<Self> {
81 match fs::read_to_string(path) {
82 Ok(contents) => Self::from_json(&contents),
83 Err(err) => Err(Error::IoError { source: err }),
84 }
85 }
86
87 pub fn to_file(&self, path: &Path) -> Result<()> {
89 let json_str = self.to_json()?.to_string();
90 fs::write(path, json_str).map_err(|source| Error::IoError { source })
91 }
92
93 pub fn from_dir(dir: &Path) -> Result<Self> {
96 let files = sorted_files(dir)?;
97 let merged = files
98 .iter()
99 .map(|f| {
100 Self::from_file(f)
101 .unwrap_or_else(|_| panic!("Error reading event log: {}", f.to_string_lossy()))
102 })
103 .fold(Self::new(), |mut merged, new| {
104 merged.0.extend(new.0);
105 merged
106 });
107 Ok(merged)
108 }
109
110 pub fn to_dir(&self, dir: &Path) -> Result<()> {
113 if !self.is_empty() {
114 if !dir.exists() {
115 fs::create_dir_all(dir)?;
116 }
117 let path = dir.join(format!("{}.json", timestamp()));
118 let json_str = self.to_json()?.to_string();
119 fs::write(path, json_str).map_err(|source| Error::IoError { source })
120 } else {
121 Ok(())
122 }
123 }
124
125 pub fn to_msgpack(&self) -> Result<Vec<u8>> {
127 let mut value = Vec::new();
128 match self.serialize(&mut rmp_serde::Serializer::new(&mut value)) {
129 Ok(_) => Ok(value),
130 Err(source) => Err(Error::MsgPackEncodeError { source }.warn()),
131 }
132 }
133
134 pub fn from_msgpack(msgpack_val: &[u8]) -> Result<Self> {
136 let cursor = io::Cursor::new(msgpack_val);
137 let mut deser = rmp_serde::decode::Deserializer::new(cursor);
138 let val = Deserialize::deserialize(&mut deser);
139 match val {
140 Ok(md) => Ok(md),
141 Err(source) => Err(Error::MsgPackDecodeError { source }.warn()),
142 }
143 }
144
145 pub fn push_event(&mut self, event: Event<T>) {
147 self.0.push(event)
148 }
149}
150
151use std::ops::Deref;
152
153impl<T> Deref for EventLog<T>
154where
155 T: Serialize + for<'lt> Deserialize<'lt> + Clone + Debug,
156{
157 type Target = Vec<Event<T>>;
158
159 fn deref(&self) -> &Self::Target {
160 &self.0
161 }
162}