wp_model_core/model/data/
storage.rs1use crate::model::DataType;
2use crate::model::Value;
3use crate::model::format::LevelFormatAble;
4use crate::model::{FNameStr, FValueStr};
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use std::fmt::{Display, Formatter};
7use std::net::IpAddr;
8use std::sync::Arc;
9
10use super::field::Field;
11use super::record::{RecordItem, RecordItemFactory};
12
13#[derive(Clone, Debug)]
41pub enum FieldStorage {
42 Shared(Arc<Field<Value>>),
47
48 Owned(Field<Value>),
53}
54
55impl FieldStorage {
56 #[inline]
73 pub fn as_field(&self) -> &Field<Value> {
74 match self {
75 FieldStorage::Shared(arc) => arc.as_ref(),
76 FieldStorage::Owned(field) => field,
77 }
78 }
79
80 pub fn into_owned(self) -> Field<Value> {
99 match self {
100 FieldStorage::Shared(arc) => {
101 Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())
103 }
104 FieldStorage::Owned(field) => field,
105 }
106 }
107
108 pub fn from_shared(field: Field<Value>) -> Self {
121 FieldStorage::Shared(Arc::new(field))
122 }
123
124 pub fn from_owned(field: Field<Value>) -> Self {
137 FieldStorage::Owned(field)
138 }
139
140 #[inline]
155 pub fn is_shared(&self) -> bool {
156 matches!(self, FieldStorage::Shared(_))
157 }
158
159 pub fn shared_count(&self) -> Option<usize> {
177 match self {
178 FieldStorage::Shared(arc) => Some(Arc::strong_count(arc)),
179 FieldStorage::Owned(_) => None,
180 }
181 }
182}
183
184impl Display for FieldStorage {
186 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
187 self.as_field().fmt(f)
188 }
189}
190
191impl PartialEq for FieldStorage {
193 fn eq(&self, other: &Self) -> bool {
194 self.as_field().eq(other.as_field())
195 }
196}
197
198impl Eq for FieldStorage {}
199
200impl Serialize for FieldStorage {
202 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
203 where
204 S: Serializer,
205 {
206 self.as_field().serialize(serializer)
208 }
209}
210
211impl<'de> Deserialize<'de> for FieldStorage {
213 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
214 where
215 D: Deserializer<'de>,
216 {
217 Field::<Value>::deserialize(deserializer).map(FieldStorage::Owned)
219 }
220}
221
222impl RecordItem for FieldStorage {
224 fn get_name(&self) -> &str {
225 self.as_field().get_name()
226 }
227
228 fn get_meta(&self) -> &DataType {
229 self.as_field().get_meta()
230 }
231
232 fn get_value(&self) -> &Value {
233 self.as_field().get_value()
234 }
235
236 fn get_value_mut(&mut self) -> &mut Value {
237 match self {
238 FieldStorage::Shared(arc) => {
239 let field = Arc::try_unwrap(std::mem::replace(
242 arc,
243 Arc::new(Field::new(DataType::Ignore, "", Value::from(false))),
244 ))
245 .unwrap_or_else(|arc| (*arc).clone());
246 *self = FieldStorage::Owned(field);
247 match self {
248 FieldStorage::Owned(f) => f.get_value_mut(),
249 _ => unreachable!(),
250 }
251 }
252 FieldStorage::Owned(field) => field.get_value_mut(),
253 }
254 }
255}
256
257impl RecordItemFactory for FieldStorage {
259 fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self {
260 FieldStorage::Owned(Field::from_digit(name, val))
261 }
262
263 fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self {
264 FieldStorage::Owned(Field::from_ip(name, ip))
265 }
266
267 fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self {
268 FieldStorage::Owned(Field::from_chars(name, val))
269 }
270}
271
272impl LevelFormatAble for FieldStorage {
274 fn level_fmt(&self, f: &mut Formatter<'_>, level: usize) -> std::fmt::Result {
275 self.as_field().level_fmt(f, level)
276 }
277}
278
279impl From<Field<Value>> for FieldStorage {
281 fn from(field: Field<Value>) -> Self {
282 FieldStorage::Owned(field)
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289 use crate::model::DataType;
290
291 #[test]
292 fn test_field_storage_shared_variant() {
293 let field = Field::new(DataType::Chars, "test", Value::from("hello"));
294 let storage = FieldStorage::Shared(Arc::new(field.clone()));
295
296 assert_eq!(storage.as_field().get_name(), "test");
298 assert!(storage.is_shared());
299 assert_eq!(storage.shared_count(), Some(1));
300
301 let storage2 = storage.clone();
303 assert_eq!(storage.shared_count(), Some(2));
304 assert_eq!(storage2.shared_count(), Some(2));
305 }
306
307 #[test]
308 fn test_field_storage_owned_variant() {
309 let field = Field::new(DataType::Digit, "test", Value::from(42));
310 let storage = FieldStorage::Owned(field);
311
312 assert_eq!(storage.as_field().get_name(), "test");
313 assert!(!storage.is_shared());
314 assert_eq!(storage.shared_count(), None);
315 }
316
317 #[test]
318 fn test_into_owned() {
319 let field1 = Field::new(DataType::Chars, "shared_field", Value::from("value"));
321 let storage1 = FieldStorage::Shared(Arc::new(field1));
322 let owned1 = storage1.into_owned();
323 assert_eq!(owned1.get_name(), "shared_field");
324
325 let field2 = Field::new(DataType::Digit, "owned_field", Value::from(123));
327 let storage2 = FieldStorage::Owned(field2);
328 let owned2 = storage2.into_owned();
329 assert_eq!(owned2.get_name(), "owned_field");
330 }
331
332 #[test]
333 fn test_from_shared() {
334 let field = Field::new(DataType::Chars, "name", Value::from("Alice"));
335 let storage = FieldStorage::from_shared(field);
336
337 assert!(storage.is_shared());
338 assert_eq!(storage.as_field().get_name(), "name");
339 }
340
341 #[test]
342 fn test_from_owned() {
343 let field = Field::new(DataType::Digit, "count", Value::from(10));
344 let storage = FieldStorage::from_owned(field);
345
346 assert!(!storage.is_shared());
347 assert_eq!(storage.as_field().get_name(), "count");
348 }
349
350 #[test]
351 fn test_display() {
352 let field = Field::new(DataType::Digit, "num", Value::from(42));
353 let storage = FieldStorage::from_owned(field);
354
355 let display = format!("{}", storage);
356 assert!(display.contains("42"));
357 }
358
359 #[test]
360 fn test_equality() {
361 let field1 = Field::new(DataType::Chars, "test", Value::from("value"));
362 let field2 = Field::new(DataType::Chars, "test", Value::from("value"));
363 let field3 = Field::new(DataType::Chars, "test", Value::from("different"));
364
365 let shared1 = FieldStorage::from_shared(field1.clone());
366 let owned1 = FieldStorage::from_owned(field1);
367 let shared2 = FieldStorage::from_shared(field2);
368 let owned3 = FieldStorage::from_owned(field3);
369
370 assert_eq!(shared1, owned1);
372 assert_eq!(shared1, shared2);
373
374 assert_ne!(shared1, owned3);
376 }
377
378 #[test]
379 fn test_serde_serialization() {
380 let field1 = Field::new(DataType::Chars, "f1", Value::from("shared"));
381 let field2 = Field::new(DataType::Digit, "f2", Value::from(99));
382
383 let shared = FieldStorage::from_shared(field1);
384 let owned = FieldStorage::from_owned(field2);
385
386 let json_shared = serde_json::to_string(&shared).unwrap();
388 let json_owned = serde_json::to_string(&owned).unwrap();
389
390 let deserialized_shared: FieldStorage = serde_json::from_str(&json_shared).unwrap();
392 let deserialized_owned: FieldStorage = serde_json::from_str(&json_owned).unwrap();
393
394 assert_eq!(deserialized_shared.as_field().get_name(), "f1");
396 assert_eq!(deserialized_owned.as_field().get_name(), "f2");
397
398 assert!(!deserialized_shared.is_shared());
400 assert!(!deserialized_owned.is_shared());
401 }
402
403 #[test]
404 fn test_clone_performance_difference() {
405 use crate::model::FValueStr;
407 let large_str = FValueStr::from("x".repeat(1000));
408 let field = Field::new(DataType::Chars, "large", Value::from(large_str));
409
410 let shared = FieldStorage::from_shared(field.clone());
412 let _shared2 = shared.clone();
413 assert_eq!(shared.shared_count(), Some(2));
414
415 let owned = FieldStorage::from_owned(field);
417 let _owned2 = owned.clone();
418 assert!(owned.shared_count().is_none());
419 }
420}