1use crate::model::format::LevelFormatAble;
2use crate::model::{DataType, FNameStr, FValueStr, Value};
3use crate::model::{FieldRef, Maker};
4use crate::traits::AsValueRef;
5use serde_derive::{Deserialize, Serialize};
6use std::convert::TryFrom;
7use std::fmt::{Display, Formatter};
8use std::net::{IpAddr, Ipv4Addr};
9use std::sync::Arc;
10
11use super::field::Field;
12use super::storage::FieldStorage;
13pub const WP_EVENT_ID: &str = "wp_event_id";
14pub trait RecordItem {
16 fn get_name(&self) -> &str;
17 fn get_meta(&self) -> &DataType;
18 fn get_value(&self) -> &Value;
19 fn get_value_mut(&mut self) -> &mut Value;
20}
21
22pub trait RecordItemFactory {
24 fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self;
25 fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self;
26 fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self;
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
30pub struct Record<T> {
31 pub id: u64,
32 pub items: Vec<T>,
33}
34
35impl<T> Default for Record<T> {
36 fn default() -> Self {
37 Self {
38 id: 0,
39 items: Vec::with_capacity(10),
40 }
41 }
42}
43
44impl<T> From<Vec<T>> for Record<T> {
45 fn from(value: Vec<T>) -> Self {
46 Self {
47 id: 0,
48 items: value,
49 }
50 }
51}
52
53impl<T> Display for Record<T>
54where
55 T: RecordItem + LevelFormatAble,
56{
57 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58 writeln!(f)?;
59 for (i, o) in self.items.iter().enumerate() {
60 if *o.get_meta() != DataType::Ignore {
61 write!(f, "NO:{:<5}", i + 1)?;
62 o.level_fmt(f, 1)?;
63 }
64 }
65 Ok(())
66 }
67}
68
69impl<T> Record<T>
70where
71 T: RecordItem + RecordItemFactory,
72{
73 pub fn set_id(&mut self, id: u64) {
74 self.id = id;
76
77 if self.items.iter().any(|f| f.get_name() == WP_EVENT_ID) {
79 return;
80 }
81 let Ok(id_i64) = i64::try_from(id) else {
82 return;
84 };
85 self.items.insert(0, T::from_digit(WP_EVENT_ID, id_i64));
86 }
87 pub fn test_value() -> Self {
88 let data = vec![
89 T::from_ip("ip", IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))),
90 T::from_chars("chars", "test"),
91 ];
92 Self { id: 0, items: data }
93 }
94}
95
96impl<T> Record<T>
97where
98 T: RecordItem,
99{
100 pub fn get_value(&self, key: &str) -> Option<&Value> {
101 self.items
102 .iter()
103 .find(|x| x.get_name() == key)
104 .map(|x| x.get_value())
105 }
106}
107
108impl<T> Record<T> {
109 pub fn len(&self) -> usize {
110 self.items.len()
111 }
112
113 pub fn is_empty(&self) -> bool {
114 self.items.is_empty()
115 }
116
117 pub fn append(&mut self, data: impl Into<T>) {
122 self.items.push(data.into());
123 }
124
125 pub fn push(&mut self, data: impl Into<T>) {
127 self.items.push(data.into());
128 }
129
130 pub fn merge(&mut self, mut other: Self) {
131 self.items.append(&mut other.items);
132 }
133}
134
135impl<T> Record<T>
136where
137 T: RecordItem,
138{
139 pub fn field(&self, key: &str) -> Option<&T> {
141 self.items.iter().find(|item| item.get_name() == key)
142 }
143
144 pub fn field_mut(&mut self, key: &str) -> Option<&mut T> {
145 self.items.iter_mut().find(|item| item.get_name() == key)
146 }
147
148 pub fn get2(&self, name: &str) -> Option<&T> {
149 self.items.iter().find(|x| x.get_name() == name)
150 }
151 pub fn get_value_mut(&mut self, name: &str) -> Option<&mut T> {
152 self.items.iter_mut().find(|x| x.get_name() == name)
153 }
154 pub fn remove_field(&mut self, name: &str) -> bool {
155 let pos = self.items.iter().position(|x| x.get_name() == name);
156 if let Some(pos) = pos {
157 self.items.remove(pos);
158 true
159 } else {
160 false
161 }
162 }
163}
164
165impl<V> RecordItem for Field<V>
166where
167 V: AsValueRef<Value>,
168{
169 fn get_name(&self) -> &str {
170 Field::get_name(self)
171 }
172
173 fn get_meta(&self) -> &DataType {
174 Field::get_meta(self)
175 }
176
177 fn get_value(&self) -> &Value {
178 Field::get_value(self)
179 }
180
181 fn get_value_mut(&mut self) -> &mut Value {
182 Field::get_value_mut(self)
183 }
184}
185
186impl<V> RecordItemFactory for Field<V>
187where
188 V: Maker<i64> + Maker<FValueStr> + Maker<IpAddr>,
189{
190 fn from_digit<S: Into<FNameStr>>(name: S, val: i64) -> Self {
191 Field::from_digit(name, val)
192 }
193
194 fn from_ip<S: Into<FNameStr>>(name: S, ip: IpAddr) -> Self {
195 Field::from_ip(name, ip)
196 }
197
198 fn from_chars<N: Into<FNameStr>, Val: Into<FValueStr>>(name: N, val: Val) -> Self {
199 Field::from_chars(name, val)
200 }
201}
202
203impl From<Vec<Field<Value>>> for Record<FieldStorage> {
205 fn from(fields: Vec<Field<Value>>) -> Self {
206 let items: Vec<FieldStorage> = fields.into_iter().map(FieldStorage::from_owned).collect();
207 Self { id: 0, items }
208 }
209}
210
211impl From<Field<Value>> for Record<FieldStorage> {
213 fn from(field: Field<Value>) -> Self {
214 Self {
215 id: 0,
216 items: vec![FieldStorage::from_owned(field)],
217 }
218 }
219}
220
221impl Record<FieldStorage> {
223 pub fn push_shared(&mut self, field: Arc<Field<Value>>) {
236 self.items.push(FieldStorage::from_shared(field));
237 }
238
239 pub fn push_owned(&mut self, field: Field<Value>) {
251 self.items.push(FieldStorage::from_owned(field));
252 }
253
254 pub fn field_at(&self, index: usize) -> Option<&Field<Value>> {
270 self.items.get(index).map(|s| s.as_field())
271 }
272
273 pub fn get_field(&self, name: &str) -> Option<FieldRef<'_>> {
290 self.field(name).map(|s| s.field_ref())
291 }
292
293 pub fn get_field_owned(&self, name: &str) -> Option<Field<Value>> {
297 self.get_field(name).map(|f| f.to_owned())
298 }
299
300 pub fn get_field_mut(&mut self, name: &str) -> Option<&mut Field<Value>> {
317 self.field_mut(name).map(|s| s.as_field_mut())
318 }
319
320 pub fn fields(&self) -> impl Iterator<Item = &Field<Value>> + '_ {
325 self.items.iter().map(|s| s.as_field())
326 }
327
328 pub fn field_refs(&self) -> impl Iterator<Item = FieldRef<'_>> + '_ {
330 self.items.iter().map(|s| s.field_ref())
331 }
332
333 pub fn fields_mut(&mut self) -> impl Iterator<Item = &mut Field<Value>> + '_ {
337 self.items.iter_mut().map(|s| s.as_field_mut())
338 }
339
340 pub fn storage_stats(&self) -> (usize, usize) {
362 let mut shared_count = 0;
363 let mut owned_count = 0;
364 for item in &self.items {
365 if item.is_shared() {
366 shared_count += 1;
367 } else {
368 owned_count += 1;
369 }
370 }
371 (shared_count, owned_count)
372 }
373
374 pub fn into_owned_record(self) -> Record<Field<Value>> {
392 Record {
393 id: self.id,
394 items: self
395 .items
396 .into_iter()
397 .map(|storage| storage.into_owned())
398 .collect(),
399 }
400 }
401}
402
403#[cfg(test)]
406mod tests {
407 use super::*;
408 use crate::model::{DataField, DataRecord, FieldStorage};
409 use std::net::Ipv4Addr;
410
411 fn make_test_record() -> DataRecord {
412 let fields = vec![
413 FieldStorage::from_chars("name", "Alice"),
414 FieldStorage::from_digit("age", 30),
415 FieldStorage::from_ip("ip", IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))),
416 ];
417 Record::from(fields)
418 }
419
420 #[test]
423 fn test_record_default() {
424 let record: DataRecord = Record::default();
425 assert!(record.items.is_empty());
426 }
427
428 #[test]
429 fn test_record_from_vec() {
430 let fields: Vec<FieldStorage> = vec![
431 FieldStorage::from_digit("x", 1),
432 FieldStorage::from_digit("y", 2),
433 ];
434 let record: DataRecord = Record::from(fields);
435 assert_eq!(record.items.len(), 2);
436 }
437
438 #[test]
439 fn test_record_test_value() {
440 let record: DataRecord = Record::test_value();
441 assert_eq!(record.items.len(), 2);
442 assert!(record.field("ip").is_some());
443 assert!(record.field("chars").is_some());
444 }
445
446 #[test]
449 fn test_record_field() {
450 let record = make_test_record();
451
452 let name_field = record.field("name");
453 assert!(name_field.is_some());
454 assert_eq!(name_field.unwrap().get_name(), "name");
455
456 let missing = record.field("missing");
457 assert!(missing.is_none());
458 }
459
460 #[test]
461 fn test_record_get2() {
462 let record = make_test_record();
463
464 let age_field = record.get2("age");
465 assert!(age_field.is_some());
466 assert_eq!(age_field.unwrap().get_meta(), &DataType::Digit);
467 }
468
469 #[test]
470 fn test_record_get_value() {
471 let record = make_test_record();
472
473 let age_value = record.get_value("age");
474 assert!(age_value.is_some());
475 assert_eq!(age_value.unwrap(), &Value::Digit(30));
476
477 let missing = record.get_value("missing");
478 assert!(missing.is_none());
479 }
480
481 #[test]
482 fn test_record_get_value_mut() {
483 let mut record = make_test_record();
484
485 let field = record.get_value_mut("age");
486 assert!(field.is_some());
487
488 if let Some(f) = field {
490 *f.get_value_mut() = Value::Digit(31);
491 }
492
493 assert_eq!(record.get_value("age"), Some(&Value::Digit(31)));
494 }
495
496 #[test]
499 fn test_record_append() {
500 let mut record: DataRecord = Record::default();
501 assert_eq!(record.items.len(), 0);
502
503 record.append(FieldStorage::from_digit("count", 100));
504 assert_eq!(record.items.len(), 1);
505
506 record.append(FieldStorage::from_chars("msg", "hello"));
507 assert_eq!(record.items.len(), 2);
508 }
509
510 #[test]
511 fn test_record_merge() {
512 let mut record1: DataRecord = Record::from(vec![FieldStorage::from_digit("a", 1)]);
513 let record2: DataRecord = Record::from(vec![
514 FieldStorage::from_digit("b", 2),
515 FieldStorage::from_digit("c", 3),
516 ]);
517
518 record1.merge(record2);
519 assert_eq!(record1.items.len(), 3);
520 assert!(record1.field("a").is_some());
521 assert!(record1.field("b").is_some());
522 assert!(record1.field("c").is_some());
523 }
524
525 #[test]
526 fn test_record_remove_field() {
527 let mut record = make_test_record();
528 assert_eq!(record.items.len(), 3);
529
530 let removed = record.remove_field("age");
531 assert!(removed);
532 assert_eq!(record.items.len(), 2);
533 assert!(record.field("age").is_none());
534
535 let not_found = record.remove_field("nonexistent");
536 assert!(!not_found);
537 assert_eq!(record.items.len(), 2);
538 }
539
540 #[test]
543 fn test_record_set_id() {
544 let mut record = make_test_record();
545 let original_len = record.items.len();
546
547 record.set_id(12345);
548
549 assert_eq!(record.id, 12345);
551 assert_eq!(record.items.len(), original_len + 1);
552 assert_eq!(record.items[0].get_name(), WP_EVENT_ID);
554 assert_eq!(record.items[0].get_value(), &Value::Digit(12345));
555 }
556
557 #[test]
558 fn test_record_set_id_no_duplicate() {
559 let mut record = make_test_record();
560
561 record.set_id(100);
562 assert_eq!(record.id, 100);
563 let len_after_first = record.items.len();
564
565 record.set_id(200);
567 assert_eq!(record.id, 200);
568 assert_eq!(record.items.len(), len_after_first);
569 assert_eq!(record.get_value(WP_EVENT_ID), Some(&Value::Digit(100)));
571 }
572
573 #[test]
576 fn test_field_as_record_item() {
577 let field: DataField = Field::from_chars("key", "value");
578
579 assert_eq!(field.get_name(), "key");
581 assert_eq!(field.get_meta(), &DataType::Chars);
582 assert_eq!(field.get_value(), &Value::Chars("value".into()));
583 }
584
585 #[test]
586 fn test_field_record_item_get_value_mut() {
587 let mut field: DataField = Field::from_digit("num", 10);
588
589 *field.get_value_mut() = Value::Digit(20);
590 assert_eq!(field.get_value(), &Value::Digit(20));
591 }
592
593 #[test]
596 fn test_field_storage_as_record_item() {
597 let storage: FieldStorage = FieldStorage::from_chars("key", "value");
598
599 assert_eq!(storage.get_name(), "key");
601 assert_eq!(storage.get_meta(), &DataType::Chars);
602 assert_eq!(storage.get_value(), &Value::Chars("value".into()));
603 }
604
605 #[test]
606 fn test_field_storage_record_item_get_value_mut() {
607 let mut storage: FieldStorage = FieldStorage::from_digit("num", 10);
608
609 *storage.get_value_mut() = Value::Digit(20);
610 assert_eq!(storage.get_value(), &Value::Digit(20));
611 }
612
613 #[test]
616 fn test_record_item_factory() {
617 let digit: FieldStorage = <FieldStorage as RecordItemFactory>::from_digit("n", 42);
618 assert_eq!(digit.get_meta(), &DataType::Digit);
619
620 let ip: FieldStorage = <FieldStorage as RecordItemFactory>::from_ip(
621 "addr",
622 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
623 );
624 assert_eq!(ip.get_meta(), &DataType::IP);
625
626 let chars: FieldStorage = <FieldStorage as RecordItemFactory>::from_chars("s", "hello");
627 assert_eq!(chars.get_meta(), &DataType::Chars);
628 }
629
630 #[test]
633 fn test_record_display() {
634 let record = make_test_record();
635 let display = format!("{}", record);
636
637 assert!(display.contains("name"));
638 assert!(display.contains("age"));
639 assert!(display.contains("ip"));
640 }
641
642 #[test]
645 fn test_push_shared() {
646 let mut record = DataRecord::default();
647 let field = Arc::new(Field::new(DataType::Chars, "static", Value::from("value")));
648
649 record.push_shared(field.clone());
650 assert_eq!(record.items.len(), 1);
651 assert!(record.items[0].is_shared());
652 assert_eq!(record.items[0].as_field().get_name(), "static");
653 }
654
655 #[test]
656 fn test_push_owned() {
657 let mut record = DataRecord::default();
658 let field = Field::new(DataType::Digit, "dynamic", Value::from(42));
659
660 record.push_owned(field);
661 assert_eq!(record.items.len(), 1);
662 assert!(!record.items[0].is_shared());
663 assert_eq!(record.items[0].as_field().get_name(), "dynamic");
664 }
665
666 #[test]
667 fn test_get_field() {
668 let mut record = DataRecord::default();
669 record.push_owned(Field::new(DataType::Chars, "test", Value::from("value")));
670
671 let field = record.field_at(0);
672 assert!(field.is_some());
673 assert_eq!(field.unwrap().get_name(), "test");
674
675 let missing = record.field_at(10);
676 assert!(missing.is_none());
677 }
678
679 #[test]
680 fn test_storage_stats() {
681 let mut record = DataRecord::default();
682
683 record.push_shared(Arc::new(Field::new(
685 DataType::Chars,
686 "s1",
687 Value::from("a"),
688 )));
689 record.push_shared(Arc::new(Field::new(
690 DataType::Chars,
691 "s2",
692 Value::from("b"),
693 )));
694
695 record.push_owned(Field::new(DataType::Digit, "o1", Value::from(1)));
697 record.push_owned(Field::new(DataType::Digit, "o2", Value::from(2)));
698 record.push_owned(Field::new(DataType::Digit, "o3", Value::from(3)));
699
700 let (shared, owned) = record.storage_stats();
701 assert_eq!(shared, 2);
702 assert_eq!(owned, 3);
703 }
704
705 #[test]
706 fn test_into_owned_record() {
707 let mut record = DataRecord::default();
708 record.push_shared(Arc::new(Field::new(
709 DataType::Chars,
710 "s",
711 Value::from("shared"),
712 )));
713 record.push_owned(Field::new(DataType::Digit, "o", Value::from(10)));
714
715 let owned_record = record.into_owned_record();
716 assert_eq!(owned_record.items.len(), 2);
717 assert_eq!(owned_record.items[0].get_name(), "s");
718 assert_eq!(owned_record.items[1].get_name(), "o");
719 }
720
721 #[test]
724 fn test_record_len_and_is_empty() {
725 let mut record = DataRecord::default();
726 assert!(record.is_empty());
727 assert_eq!(record.len(), 0);
728
729 record.append(FieldStorage::from_chars("a", "1"));
730 assert!(!record.is_empty());
731 assert_eq!(record.len(), 1);
732 }
733
734 #[test]
735 fn test_from_vec_datafield() {
736 let fields: Vec<DataField> = vec![
737 DataField::from_chars("a", "1"),
738 DataField::from_chars("b", "2"),
739 ];
740 let record = DataRecord::from(fields);
741 assert_eq!(record.len(), 2);
742 assert!(record.field("a").is_some());
743 assert!(record.field("b").is_some());
744 }
745
746 #[test]
747 fn test_from_single_datafield() {
748 let field = DataField::from_chars("name", "Alice");
749 let record = DataRecord::from(field);
750 assert_eq!(record.len(), 1);
751 assert!(record.field("name").is_some());
752 }
753
754 #[test]
755 fn test_append_generic() {
756 let mut record = DataRecord::default();
757
758 record.append(DataField::from_chars("a", "1"));
760
761 record.append(FieldStorage::from_chars("b", "2"));
763
764 let arc_field = Arc::new(DataField::from_chars("c", "3"));
766 record.append(arc_field);
767
768 assert_eq!(record.len(), 3);
769 assert!(record.items[0].is_owned());
770 assert!(record.items[1].is_owned());
771 assert!(record.items[2].is_shared());
772 }
773
774 #[test]
775 fn test_push_alias() {
776 let mut record = DataRecord::default();
777 record.push(DataField::from_chars("a", "1"));
778 record.push(FieldStorage::from_chars("b", "2"));
779 assert_eq!(record.len(), 2);
780 }
781
782 #[test]
783 fn test_get_field_by_name() {
784 let record = DataRecord::from(vec![
785 DataField::from_chars("name", "Alice"),
786 DataField::from_digit("age", 30),
787 ]);
788
789 let field = record.get_field("name");
790 assert!(field.is_some());
791 assert_eq!(field.unwrap().get_name(), "name");
792
793 assert!(record.get_field("missing").is_none());
794 }
795
796 #[test]
797 fn test_get_field_mut_by_name() {
798 let mut record = DataRecord::from(vec![DataField::from_chars("name", "Alice")]);
799
800 if let Some(field) = record.get_field_mut("name") {
801 field.set_name("renamed");
802 }
803 assert_eq!(
804 record.get_field("renamed").map(|f| f.get_name()),
805 Some("renamed")
806 );
807 }
808
809 #[test]
810 fn test_field_mut() {
811 let mut record = DataRecord::from(vec![DataField::from_chars("name", "Alice")]);
812
813 let storage = record.field_mut("name");
814 assert!(storage.is_some());
815 }
816
817 #[test]
818 fn test_fields_iterator() {
819 let record = DataRecord::from(vec![
820 DataField::from_chars("a", "1"),
821 DataField::from_chars("b", "2"),
822 DataField::from_chars("c", "3"),
823 ]);
824
825 let names: Vec<&str> = record.fields().map(|f| f.get_name()).collect();
826 assert_eq!(names, vec!["a", "b", "c"]);
827 }
828
829 #[test]
830 fn test_fields_mut_iterator() {
831 let mut record = DataRecord::from(vec![DataField::from_chars("a", "1")]);
832
833 for field in record.fields_mut() {
834 field.set_name("renamed");
835 }
836 assert_eq!(
837 record.get_field("renamed").map(|f| f.get_name()),
838 Some("renamed")
839 );
840 }
841}