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 #[inline]
195 pub fn is_owned(&self) -> bool {
196 matches!(self, FieldStorage::Owned(_))
197 }
198
199 pub fn as_field_mut(&mut self) -> &mut Field<Value> {
214 if let FieldStorage::Shared(_) = self {
215 let old = std::mem::replace(
216 self,
217 FieldStorage::Owned(Field::new(DataType::Ignore, "", Value::from(false))),
218 );
219 *self = FieldStorage::Owned(old.into_owned());
220 }
221 match self {
222 FieldStorage::Owned(field) => field,
223 FieldStorage::Shared(_) => unreachable!(),
224 }
225 }
226}
227
228impl Display for FieldStorage {
230 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
231 self.as_field().fmt(f)
232 }
233}
234
235impl PartialEq for FieldStorage {
237 fn eq(&self, other: &Self) -> bool {
238 self.as_field().eq(other.as_field())
239 }
240}
241
242impl Eq for FieldStorage {}
243
244impl Serialize for FieldStorage {
246 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
247 where
248 S: Serializer,
249 {
250 self.as_field().serialize(serializer)
252 }
253}
254
255impl<'de> Deserialize<'de> for FieldStorage {
257 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
258 where
259 D: Deserializer<'de>,
260 {
261 Field::<Value>::deserialize(deserializer).map(FieldStorage::Owned)
263 }
264}
265
266impl RecordItem for FieldStorage {
268 fn get_name(&self) -> &str {
269 self.as_field().get_name()
270 }
271
272 fn get_meta(&self) -> &DataType {
273 self.as_field().get_meta()
274 }
275
276 fn get_value(&self) -> &Value {
277 self.as_field().get_value()
278 }
279
280 fn get_value_mut(&mut self) -> &mut Value {
281 self.as_field_mut().get_value_mut()
282 }
283}
284
285impl RecordItemFactory for FieldStorage {
287 fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self {
288 FieldStorage::Owned(Field::from_digit(name, val))
289 }
290
291 fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self {
292 FieldStorage::Owned(Field::from_ip(name, ip))
293 }
294
295 fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self {
296 FieldStorage::Owned(Field::from_chars(name, val))
297 }
298}
299
300impl LevelFormatAble for FieldStorage {
302 fn level_fmt(&self, f: &mut Formatter<'_>, level: usize) -> std::fmt::Result {
303 self.as_field().level_fmt(f, level)
304 }
305}
306
307impl From<Field<Value>> for FieldStorage {
309 fn from(field: Field<Value>) -> Self {
310 FieldStorage::Owned(field)
311 }
312}
313
314impl From<Arc<Field<Value>>> for FieldStorage {
315 fn from(arc: Arc<Field<Value>>) -> Self {
316 FieldStorage::Shared(arc)
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use super::*;
323 use crate::model::DataType;
324
325 #[test]
326 fn test_field_storage_shared_variant() {
327 let field = Field::new(DataType::Chars, "test", Value::from("hello"));
328 let storage = FieldStorage::Shared(Arc::new(field.clone()));
329
330 assert_eq!(storage.as_field().get_name(), "test");
332 assert!(storage.is_shared());
333 assert_eq!(storage.shared_count(), Some(1));
334
335 let storage2 = storage.clone();
337 assert_eq!(storage.shared_count(), Some(2));
338 assert_eq!(storage2.shared_count(), Some(2));
339 }
340
341 #[test]
342 fn test_field_storage_owned_variant() {
343 let field = Field::new(DataType::Digit, "test", Value::from(42));
344 let storage = FieldStorage::Owned(field);
345
346 assert_eq!(storage.as_field().get_name(), "test");
347 assert!(!storage.is_shared());
348 assert_eq!(storage.shared_count(), None);
349 }
350
351 #[test]
352 fn test_into_owned() {
353 let field1 = Field::new(DataType::Chars, "shared_field", Value::from("value"));
355 let storage1 = FieldStorage::Shared(Arc::new(field1));
356 let owned1 = storage1.into_owned();
357 assert_eq!(owned1.get_name(), "shared_field");
358
359 let field2 = Field::new(DataType::Digit, "owned_field", Value::from(123));
361 let storage2 = FieldStorage::Owned(field2);
362 let owned2 = storage2.into_owned();
363 assert_eq!(owned2.get_name(), "owned_field");
364 }
365
366 #[test]
367 fn test_from_shared() {
368 let field = Field::new(DataType::Chars, "name", Value::from("Alice"));
369 let storage = FieldStorage::from_shared(field);
370
371 assert!(storage.is_shared());
372 assert_eq!(storage.as_field().get_name(), "name");
373 }
374
375 #[test]
376 fn test_from_owned() {
377 let field = Field::new(DataType::Digit, "count", Value::from(10));
378 let storage = FieldStorage::from_owned(field);
379
380 assert!(!storage.is_shared());
381 assert_eq!(storage.as_field().get_name(), "count");
382 }
383
384 #[test]
385 fn test_display() {
386 let field = Field::new(DataType::Digit, "num", Value::from(42));
387 let storage = FieldStorage::from_owned(field);
388
389 let display = format!("{}", storage);
390 assert!(display.contains("42"));
391 }
392
393 #[test]
394 fn test_equality() {
395 let field1 = Field::new(DataType::Chars, "test", Value::from("value"));
396 let field2 = Field::new(DataType::Chars, "test", Value::from("value"));
397 let field3 = Field::new(DataType::Chars, "test", Value::from("different"));
398
399 let shared1 = FieldStorage::from_shared(field1.clone());
400 let owned1 = FieldStorage::from_owned(field1);
401 let shared2 = FieldStorage::from_shared(field2);
402 let owned3 = FieldStorage::from_owned(field3);
403
404 assert_eq!(shared1, owned1);
406 assert_eq!(shared1, shared2);
407
408 assert_ne!(shared1, owned3);
410 }
411
412 #[test]
413 fn test_serde_serialization() {
414 let field1 = Field::new(DataType::Chars, "f1", Value::from("shared"));
415 let field2 = Field::new(DataType::Digit, "f2", Value::from(99));
416
417 let shared = FieldStorage::from_shared(field1);
418 let owned = FieldStorage::from_owned(field2);
419
420 let json_shared = serde_json::to_string(&shared).unwrap();
422 let json_owned = serde_json::to_string(&owned).unwrap();
423
424 let deserialized_shared: FieldStorage = serde_json::from_str(&json_shared).unwrap();
426 let deserialized_owned: FieldStorage = serde_json::from_str(&json_owned).unwrap();
427
428 assert_eq!(deserialized_shared.as_field().get_name(), "f1");
430 assert_eq!(deserialized_owned.as_field().get_name(), "f2");
431
432 assert!(!deserialized_shared.is_shared());
434 assert!(!deserialized_owned.is_shared());
435 }
436
437 #[test]
438 fn test_clone_performance_difference() {
439 use crate::model::FValueStr;
441 let large_str = FValueStr::from("x".repeat(1000));
442 let field = Field::new(DataType::Chars, "large", Value::from(large_str));
443
444 let shared = FieldStorage::from_shared(field.clone());
446 let _shared2 = shared.clone();
447 assert_eq!(shared.shared_count(), Some(2));
448
449 let owned = FieldStorage::from_owned(field);
451 let _owned2 = owned.clone();
452 assert!(owned.shared_count().is_none());
453 }
454
455 #[test]
456 fn test_from_arc_to_fieldstorage() {
457 let field = Field::new(DataType::Chars, "name", Value::from("Alice"));
458 let arc = Arc::new(field);
459 let storage: FieldStorage = arc.into();
460
461 assert!(storage.is_shared());
462 assert_eq!(storage.as_field().get_name(), "name");
463 }
464
465 #[test]
466 fn test_is_owned() {
467 let field = Field::new(DataType::Digit, "x", Value::from(1));
468 let owned = FieldStorage::from_owned(field.clone());
469 let shared = FieldStorage::from_shared(field);
470
471 assert!(owned.is_owned());
472 assert!(!shared.is_owned());
473 }
474
475 #[test]
476 fn test_as_field_mut_owned() {
477 let mut storage = FieldStorage::from_owned(Field::from_chars("name", "Alice"));
478 storage.as_field_mut().set_name("renamed");
479 assert_eq!(storage.as_field().get_name(), "renamed");
480 assert!(storage.is_owned());
481 }
482
483 #[test]
484 fn test_as_field_mut_shared() {
485 let field = Field::from_chars("name", "Alice");
486 let mut storage = FieldStorage::from_shared(field);
487 assert!(storage.is_shared());
488
489 storage.as_field_mut().set_name("renamed");
491 assert!(storage.is_owned());
492 assert_eq!(storage.as_field().get_name(), "renamed");
493 }
494}