1use serde::{Deserialize, Serialize};
2
3use crate::{DataType, IdType};
4
5use super::types::{EpochMillisType, VersionType};
6
7#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
10pub struct Model<Id, Data> {
11 pub id: Id,
13 pub version: VersionType,
15 #[serde(default)]
17 pub create_epoch_millis: EpochMillisType,
18 #[serde(default)]
20 pub update_epoch_millis: EpochMillisType,
21 pub data: Data,
23}
24
25impl<Id: IdType, Data: DataType> Model<Id, Data> {
26 pub fn into_new(self) -> NewModel<Data> {
29 NewModel::new(self.data)
30 }
31
32 pub fn from_new(
42 id: Id,
43 create_epoch_millis: EpochMillisType,
44 model: NewModel<Data>,
45 ) -> Model<Id, Data> {
46 Model {
47 id,
48 version: model.version,
49 create_epoch_millis,
50 update_epoch_millis: create_epoch_millis,
51 data: model.data,
52 }
53 }
54
55 pub fn into_new_version(self, update_epoch_millis: EpochMillisType) -> Model<Id, Data> {
65 Model {
66 id: self.id,
67 version: self.version + 1,
68 create_epoch_millis: self.create_epoch_millis,
69 update_epoch_millis,
70 data: self.data,
71 }
72 }
73}
74
75#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
78pub struct NewModel<Data> {
79 pub version: VersionType,
80 pub data: Data,
81}
82
83impl<Data: DataType> NewModel<Data> {
84 pub fn new(data: Data) -> Self {
87 NewModel { version: 0, data }
88 }
89}
90
91impl<Data: DataType + Default> Default for NewModel<Data> {
92 fn default() -> Self {
93 NewModel::new(Data::default())
94 }
95}
96
97impl<Data> From<Data> for NewModel<Data>
98where
99 Data: DataType,
100{
101 fn from(data: Data) -> Self {
102 NewModel::new(data)
103 }
104}
105
106#[cfg(test)]
107mod test {
108
109 use super::*;
110 use serde::{Deserialize, Serialize};
111 use serde_json;
112
113 #[test]
114 fn model_should_be_serializable() -> Result<(), Box<dyn std::error::Error>> {
115 let model = Model {
116 id: 1,
117 version: 1,
118 data: SimpleData {
119 name: "test".to_owned(),
120 },
121 create_epoch_millis: 0,
122 update_epoch_millis: 0,
123 };
124
125 let serialize = serde_json::to_string(&model)?;
126 let deserialize: Model<i64, SimpleData> = serde_json::from_str(&serialize)?;
127
128 assert_eq!(model.id, deserialize.id);
129 assert_eq!(model.version, deserialize.version);
130 assert_eq!(model.data, deserialize.data);
131
132 Ok(())
133 }
134
135 #[test]
136 fn new_model_should_be_serializable() -> Result<(), Box<dyn std::error::Error>> {
137 let model = NewModel::new(SimpleData {
138 name: "test".to_owned(),
139 });
140
141 let serialize = serde_json::to_string(&model)?;
142 let deserialize: NewModel<SimpleData> = serde_json::from_str(&serialize)?;
143
144 assert_eq!(model.version, deserialize.version);
145 assert_eq!(model.data, deserialize.data);
146 Ok(())
147 }
148
149 #[test]
150 fn model_should_impl_debug_if_data_is_debug() {
151 let model = Model {
152 id: 1,
153 version: 1,
154 data: SimpleData {
155 name: "test".to_owned(),
156 },
157 create_epoch_millis: 0,
158 update_epoch_millis: 0,
159 };
160
161 println!("Debug model: {:?}", model);
162 }
163
164 #[test]
165 fn new_model_should_impl_debug_if_data_is_debug() {
166 let model = NewModel::new(SimpleData {
167 name: "test".to_owned(),
168 });
169
170 println!("Debug model: {:?}", model);
171 }
172
173 #[test]
174 fn new_model_from_model_should_have_new_version() {
175 let model = Model {
176 id: 10,
177 version: 10,
178 data: SimpleData {
179 name: "test".to_owned(),
180 },
181 create_epoch_millis: 0,
182 update_epoch_millis: 0,
183 };
184
185 let new_model = model.clone().into_new();
186
187 assert_eq!(model.data, new_model.data);
188 assert_eq!(new_model.version, 0);
189 }
190
191 #[test]
192 fn should_build_new_model_version() {
193 let model = Model {
194 id: 10,
195 version: 10,
196 data: SimpleData {
197 name: "test".to_owned(),
198 },
199 create_epoch_millis: 0,
200 update_epoch_millis: 0,
201 };
202
203 let new_update_epoch_millis = 111;
204
205 let new_model_version = model.clone().into_new_version(new_update_epoch_millis);
206
207 assert_eq!(model.data, new_model_version.data);
208 assert_eq!(model.id, new_model_version.id);
209 assert_eq!(
210 model.create_epoch_millis,
211 new_model_version.create_epoch_millis
212 );
213 assert_eq!(
214 new_update_epoch_millis,
215 new_model_version.update_epoch_millis
216 );
217 assert_eq!(model.version + 1, new_model_version.version);
218 }
219
220 #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
221 struct SimpleData {
222 name: String,
223 }
224}