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