1use crate::common::PageID;
2use crate::common::Position;
3use crate::page::PAGE_HEADER_SIZE;
4use crate::slice_reader::SliceReader;
5use bitflags::bitflags;
6use rustc_hash::FxHashSet;
7use std::io::{Cursor, Write};
8use umadb_dcb::DcbError;
9use umadb_dcb::DcbResult;
10use uuid::Uuid;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct EventRecord {
14 pub event_type: String,
15 pub data: Vec<u8>,
16 pub tags: Vec<String>,
17 pub uuid: Option<Uuid>,
18 pub metadata: Vec<(String, String)>,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum EventValue {
23 Inline(EventRecord),
24 Overflow {
26 event_type: String,
27 data_len: u64,
28 tags: Vec<String>,
29 root_id: PageID,
30 uuid: Option<Uuid>,
31 metadata_len: u64,
32 },
33}
34
35pub const MAX_METADATA_ENTRIES: usize = u16::MAX as usize;
38
39pub const MAX_METADATA_ENTRY_LEN: usize = u16::MAX as usize;
42
43pub const MAX_EVENT_TYPE_LEN: usize = u16::MAX as usize;
46
47pub const MAX_TAGS: usize = u16::MAX as usize;
50
51pub const MAX_TAG_LEN: usize = u16::MAX as usize;
54
55pub fn validate_event_record_for_append(
56 page_size: usize,
57 record: EventRecord,
58) -> DcbResult<((EventValue, usize), Option<(EventValue, usize)>)> {
59 validate_tags(&record.tags)?;
61 validate_metadata(&record.metadata)?;
62
63 let mut node = EventLeafNode {
64 keys: vec![],
65 values: vec![],
66 };
67 let empty_size = node.calc_serialized_size();
68 node.keys.push(Position(0));
69 node.values.push(EventValue::Inline(record));
70 let inline_size = node.calc_serialized_size();
71 let inline_value = node.values.pop().expect("node has one value");
72
73 if inline_size + PAGE_HEADER_SIZE <= page_size {
74 return Ok(((inline_value, inline_size - empty_size), None));
75 }
76
77 let overflow_value = match &inline_value {
78 EventValue::Inline(record) => {
79 EventValue::Overflow {
80 event_type: record.event_type.clone(),
81 data_len: record.data.len() as u64,
82 tags: record.tags.clone(),
83 root_id: PageID(0),
84 uuid: record.uuid,
85 metadata_len: if record.metadata.is_empty() {
86 0
87 } else {
88 1
90 },
91 }
92 }
93 EventValue::Overflow { .. } => {
94 return Err(DcbError::InternalError("Shouldn't get here".to_string()));
95 }
96 };
97
98 node.values.push(overflow_value);
99 let overflow_size = node.calc_serialized_size();
100 let overflow_value = node.values.pop().expect("node has one value");
101
102 if !(overflow_size + PAGE_HEADER_SIZE <= page_size) {
103 return Err(DcbError::InvalidArgument(
104 "event too large for page size".to_string(),
105 ));
106 }
107 Ok((
108 (inline_value, inline_size - empty_size),
109 Some((overflow_value, overflow_size - empty_size)),
110 ))
111}
112
113pub fn validate_tags(tags: &[String]) -> DcbResult<()> {
128 if tags.len() > MAX_TAGS {
129 return Err(DcbError::InvalidArgument(format!(
130 "event has {} tags, exceeding the maximum of {}",
131 tags.len(),
132 MAX_TAGS
133 )));
134 }
135 Ok(())
145}
146
147pub fn validate_metadata(metadata: &[(String, String)]) -> DcbResult<()> {
152 if metadata.len() > MAX_METADATA_ENTRIES {
153 return Err(DcbError::InvalidArgument(format!(
154 "metadata has {} entries, exceeding the maximum of {}",
155 metadata.len(),
156 MAX_METADATA_ENTRIES
157 )));
158 }
159 if has_duplicate_metadata_key(metadata) {
160 return Err(DcbError::InvalidArgument(
161 "metadata contains duplicate keys".to_string(),
162 ));
163 }
164 for (k, v) in metadata {
165 if k.len() > MAX_METADATA_ENTRY_LEN {
166 return Err(DcbError::InvalidArgument(format!(
167 "metadata key has length {} bytes, exceeding the maximum of {}",
168 k.len(),
169 MAX_METADATA_ENTRY_LEN
170 )));
171 }
172 if v.len() > MAX_METADATA_ENTRY_LEN {
173 return Err(DcbError::InvalidArgument(format!(
174 "metadata value for key '{}' has length {} bytes, exceeding the maximum of {}",
175 k,
176 v.len(),
177 MAX_METADATA_ENTRY_LEN
178 )));
179 }
180 }
181 Ok(())
182}
183
184pub fn has_duplicate_metadata_key(metadata: &[(String, String)]) -> bool {
187 if metadata.len() < 2 {
189 return false;
190 }
191
192 if metadata.len() < 9 {
194 for (i, (k1, _)) in metadata.iter().enumerate() {
195 if metadata[i + 1..].iter().any(|(k2, _)| k1 == k2) {
197 return true;
198 }
199 }
200 return false;
201 }
202
203 let mut set = FxHashSet::with_capacity_and_hasher(metadata.len(), Default::default());
205
206 metadata.iter().any(|(k, _)| !set.insert(k))
208}
209
210pub fn metadata_serialized_size(metadata: &[(String, String)]) -> usize {
215 let mut size = 2; for (k, v) in metadata {
217 size += 2 + k.len() + 2 + v.len();
218 }
219 size
220}
221
222pub fn serialize_metadata_into(metadata: &[(String, String)], buf: &mut [u8]) -> DcbResult<usize> {
224 let mut cursor = Cursor::new(buf);
227
228 let n = metadata.len() as u16;
230 cursor.write_all(&n.to_le_bytes())?;
231
232 for (k, v) in metadata {
235 let kl = k.len() as u16;
236 cursor.write_all(&kl.to_le_bytes())?;
237 cursor.write_all(k.as_bytes())?;
238
239 let vl = v.len() as u16;
240 cursor.write_all(&vl.to_le_bytes())?;
241 cursor.write_all(v.as_bytes())?;
242 }
243
244 Ok(cursor.position() as usize)
246}
247
248pub fn serialize_metadata(metadata: &[(String, String)]) -> Vec<u8> {
251 let mut buf = vec![0u8; metadata_serialized_size(metadata)];
252 serialize_metadata_into(metadata, &mut buf).unwrap();
253 buf
254}
255
256fn read_metadata(reader: &mut SliceReader<'_>) -> DcbResult<Vec<(String, String)>> {
258 let n = reader.read_u16()? as usize;
259 let mut metadata = Vec::with_capacity(n);
260
261 for _ in 0..n {
262 let kl = reader.read_u16()? as usize;
263 let key = reader.read_string(kl)?;
264
265 let vl = reader.read_u16()? as usize;
266 let value = reader.read_string(vl)?;
267
268 metadata.push((key, value));
269 }
270
271 Ok(metadata)
272}
273
274pub fn deserialize_metadata(slice: &[u8]) -> DcbResult<Vec<(String, String)>> {
277 let mut reader = SliceReader::new(slice);
278 read_metadata(&mut reader)
279}
280
281impl PartialEq<EventValue> for EventRecord {
282 fn eq(&self, other: &EventValue) -> bool {
283 match other {
284 EventValue::Inline(rec) => self == rec,
285 EventValue::Overflow {
286 event_type,
287 data_len,
288 tags,
289 ..
290 } => {
291 &self.event_type == event_type
292 && &self.tags == tags
293 && (self.data.len() as u64) == *data_len
294 }
295 }
296 }
297}
298
299impl PartialEq<EventRecord> for EventValue {
300 fn eq(&self, other: &EventRecord) -> bool {
301 other == self
302 }
303}
304
305bitflags! {
306 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
307 pub struct EventValueFlags: u8 {
308 const OVERFLOW = 0b0000_0001; const HAS_UUID = 0b0000_0010; const HAS_METADATA = 0b0000_0100; }
312}
313
314#[derive(Debug, Clone, PartialEq, Eq)]
315pub struct EventLeafNode {
316 pub keys: Vec<Position>,
317 pub values: Vec<EventValue>,
318}
319
320impl EventLeafNode {
321 pub fn calc_serialized_size(&self) -> usize {
322 let mut total_size = 2;
324
325 total_size += self.keys.len() * 8;
327
328 for value in &self.values {
330 total_size += 1;
332 match value {
333 EventValue::Inline(rec) => {
334 total_size += 2 + rec.event_type.len();
336 total_size += 2 + rec.data.len();
338 total_size += 2;
340 for tag in &rec.tags {
342 total_size += 2 + tag.len();
343 }
344 if rec.uuid.is_some() {
345 total_size += 16;
346 }
347 if !rec.metadata.is_empty() {
348 total_size += metadata_serialized_size(&rec.metadata);
349 }
350 }
351 EventValue::Overflow {
352 event_type,
353 data_len: _,
354 tags,
355 root_id: _,
356 uuid,
357 metadata_len,
358 } => {
359 total_size += 2 + event_type.len();
361 total_size += 8;
363 total_size += 2;
365 for tag in tags {
367 total_size += 2 + tag.len();
368 }
369 total_size += 8;
371 if uuid.is_some() {
372 total_size += 16;
373 }
374 if *metadata_len > 0 {
375 total_size += 8;
377 }
378 }
379 }
380 }
381
382 total_size
383 }
384
385 pub fn serialize_into(&self, buf: &mut [u8]) -> DcbResult<usize> {
387 let mut cursor = Cursor::new(buf);
388
389 let klen = self.keys.len() as u16;
391 cursor.write_all(&klen.to_le_bytes())?;
392
393 for key in &self.keys {
395 cursor.write_all(&key.0.to_le_bytes())?;
396 }
397
398 for value in &self.values {
400 let mut flags = EventValueFlags::empty();
401 match value {
402 EventValue::Inline(rec) => {
403 if rec.uuid.is_some() {
404 flags |= EventValueFlags::HAS_UUID;
405 }
406 if !rec.metadata.is_empty() {
407 flags |= EventValueFlags::HAS_METADATA;
408 }
409 cursor.write_all(&[flags.bits()])?;
410
411 let et_len = rec.event_type.len() as u16;
412 cursor.write_all(&et_len.to_le_bytes())?;
413 cursor.write_all(rec.event_type.as_bytes())?;
414
415 let dlen = rec.data.len() as u16;
416 cursor.write_all(&dlen.to_le_bytes())?;
417 cursor.write_all(&rec.data)?;
418
419 let tlen = rec.tags.len() as u16;
420 cursor.write_all(&tlen.to_le_bytes())?;
421
422 for tag in &rec.tags {
423 let tl = tag.len() as u16;
424 cursor.write_all(&tl.to_le_bytes())?;
425 cursor.write_all(tag.as_bytes())?;
426 }
427
428 if let Some(uuid) = rec.uuid {
429 cursor.write_all(uuid.as_bytes())?;
430 }
431
432 if !rec.metadata.is_empty() {
433 let pos = cursor.position() as usize;
434 let remaining_buf = &mut cursor.get_mut()[pos..];
435
436 let written = serialize_metadata_into(&rec.metadata, remaining_buf)?;
438
439 cursor.set_position((pos + written) as u64);
441 }
442 }
443 EventValue::Overflow {
444 event_type,
445 data_len,
446 tags,
447 root_id,
448 uuid,
449 metadata_len,
450 } => {
451 flags |= EventValueFlags::OVERFLOW;
452 if uuid.is_some() {
453 flags |= EventValueFlags::HAS_UUID;
454 }
455 if *metadata_len > 0 {
456 flags |= EventValueFlags::HAS_METADATA;
457 }
458 cursor.write_all(&[flags.bits()])?;
459
460 let et_len = event_type.len() as u16;
461 cursor.write_all(&et_len.to_le_bytes())?;
462 cursor.write_all(event_type.as_bytes())?;
463
464 cursor.write_all(&data_len.to_le_bytes())?;
465
466 let tlen = tags.len() as u16;
467 cursor.write_all(&tlen.to_le_bytes())?;
468
469 for tag in tags {
470 let tl = tag.len() as u16;
471 cursor.write_all(&tl.to_le_bytes())?;
472 cursor.write_all(tag.as_bytes())?;
473 }
474
475 cursor.write_all(&root_id.0.to_le_bytes())?;
476
477 if let Some(uuid_val) = uuid {
478 cursor.write_all(uuid_val.as_bytes())?;
479 }
480
481 if *metadata_len > 0 {
482 cursor.write_all(&metadata_len.to_le_bytes())?;
483 }
484 }
485 }
486 }
487
488 Ok(cursor.position() as usize)
489 }
490
491 pub fn from_slice(slice: &[u8]) -> DcbResult<Self> {
492 let mut reader = SliceReader::new(slice);
493
494 let keys_len = reader.read_u16()? as usize;
496 let mut keys = Vec::with_capacity(keys_len);
497 for _ in 0..keys_len {
498 keys.push(reader.read_position()?);
499 }
500
501 let mut values = Vec::with_capacity(keys_len);
503
504 for _ in 0..keys_len {
505 let flags_byte = reader.read_u8()?;
507 let flags = EventValueFlags::from_bits(flags_byte).ok_or_else(|| {
508 DcbError::DeserializationError("unknown flag bits set".to_string())
509 })?;
510
511 let event_type_len = reader.read_u16()? as usize;
513 let event_type = reader.read_string(event_type_len)?;
514
515 let overflow = flags.contains(EventValueFlags::OVERFLOW);
516 let has_uuid = flags.contains(EventValueFlags::HAS_UUID);
517 let has_metadata = flags.contains(EventValueFlags::HAS_METADATA);
518
519 if !overflow {
520 let data_len = reader.read_u16()? as usize;
522 let data = reader.read_bytes(data_len)?.to_vec();
523
524 let num_tags = reader.read_u16()? as usize;
525 let mut tags = Vec::with_capacity(num_tags);
526 for _ in 0..num_tags {
527 let tag_len = reader.read_u16()? as usize;
528 let tag = reader.read_string(tag_len)?;
529 tags.push(tag);
530 }
531 let uuid = if has_uuid {
532 Some(reader.read_uuid()?)
533 } else {
534 None
535 };
536 let metadata = if has_metadata {
537 read_metadata(&mut reader)?
538 } else {
539 Vec::new()
540 };
541
542 values.push(EventValue::Inline(EventRecord {
543 event_type,
544 data,
545 tags,
546 uuid,
547 metadata,
548 }));
549 } else {
550 let data_len = reader.read_u64()?;
552
553 let num_tags = reader.read_u16()? as usize;
554 let mut tags = Vec::with_capacity(num_tags);
555 for _ in 0..num_tags {
556 let tag_len = reader.read_u16()? as usize;
557 let tag = reader.read_string(tag_len)?;
558 tags.push(tag);
559 }
560
561 let root_id = reader.read_page_id()?;
562
563 let uuid = if has_uuid {
564 Some(reader.read_uuid()?)
565 } else {
566 None
567 };
568
569 let metadata_len = if has_metadata { reader.read_u64()? } else { 0 };
570
571 values.push(EventValue::Overflow {
572 event_type,
573 data_len,
574 tags,
575 root_id,
576 uuid,
577 metadata_len,
578 });
579 }
580 }
581
582 Ok(EventLeafNode { keys, values })
583 }
584
585 pub fn pop_last_key_and_value(&mut self) -> DcbResult<(Position, EventValue)> {
586 let last_key = self
587 .keys
588 .pop()
589 .expect("EventLeafNode should have some keys");
590 let last_value = self
591 .values
592 .pop()
593 .expect("EventLeafNode should have some values");
594 Ok((last_key, last_value))
595 }
596}
597
598#[derive(Debug, Clone, PartialEq, Eq)]
599pub struct EventOverflowNode {
600 pub next: PageID, pub data: Vec<u8>,
602}
603
604impl EventOverflowNode {
605 pub fn calc_serialized_size(&self) -> usize {
606 8 + self.data.len()
608 }
609
610 pub fn serialize_into(&self, buf: &mut [u8]) -> DcbResult<usize> {
611 let mut cursor = Cursor::new(buf);
612
613 cursor.write_all(&self.next.0.to_le_bytes())?;
615
616 cursor.write_all(&self.data)?;
618
619 Ok(cursor.position() as usize)
620 }
621
622 pub fn from_slice(slice: &[u8]) -> DcbResult<Self> {
623 let mut reader = SliceReader::new(slice);
624
625 let next = reader.read_page_id()?;
627
628 let data = reader.read_bytes(reader.remaining())?.to_vec();
630
631 Ok(Self { next, data })
632 }
633}
634
635#[derive(Debug, Clone, PartialEq, Eq)]
636pub struct EventInternalNode {
637 pub keys: Vec<Position>,
638 pub child_ids: Vec<PageID>,
639}
640
641impl EventInternalNode {
642 pub fn calc_serialized_size(&self) -> usize {
643 let mut total_size = 2;
645
646 total_size += self.keys.len() * 8;
648
649 total_size += self.child_ids.len() * 8;
651
652 total_size
653 }
654
655 pub fn serialize_into(&self, buf: &mut [u8]) -> DcbResult<usize> {
656 let mut cursor = Cursor::new(buf);
657
658 let klen = self.keys.len() as u16;
660 cursor.write_all(&klen.to_le_bytes())?;
661
662 for key in &self.keys {
664 cursor.write_all(&key.0.to_le_bytes())?;
665 }
666
667 for child_id in &self.child_ids {
669 cursor.write_all(&child_id.0.to_le_bytes())?;
670 }
671
672 Ok(cursor.position() as usize)
673 }
674
675 pub fn from_slice(slice: &[u8]) -> DcbResult<Self> {
676 let mut reader = SliceReader::new(slice);
677
678 let keys_len = reader.read_u16()? as usize;
680
681 let mut keys = Vec::with_capacity(keys_len);
683 for _ in 0..keys_len {
684 keys.push(reader.read_position()?);
685 }
686
687 let child_ids_len = keys_len + 1;
689
690 let mut child_ids = Vec::with_capacity(child_ids_len);
692 for _ in 0..child_ids_len {
693 child_ids.push(reader.read_page_id()?);
694 }
695
696 Ok(EventInternalNode { keys, child_ids })
697 }
698
699 pub fn replace_last_child_id(&mut self, old_id: PageID, new_id: PageID) -> DcbResult<()> {
700 let last_idx = self.child_ids.len() - 1;
702 if self.child_ids[last_idx] == old_id {
703 self.child_ids[last_idx] = new_id;
704 } else {
705 return Err(DcbError::DatabaseCorrupted("Child ID mismatch".to_string()));
706 }
707 Ok(())
708 }
709 pub fn append_promoted_key_and_page_id(
710 &mut self,
711 promoted_key: Position,
712 promoted_page_id: PageID,
713 ) -> DcbResult<()> {
714 self.keys.push(promoted_key);
715 self.child_ids.push(promoted_page_id);
716 Ok(())
717 }
718 pub fn split_off(&mut self) -> DcbResult<(Position, Vec<Position>, Vec<PageID>)> {
719 let middle_idx = self.keys.len() - 2;
720 let promoted_key = self.keys.remove(middle_idx);
721 let new_keys = self.keys.split_off(middle_idx);
722 let new_child_ids = self.child_ids.split_off(middle_idx + 1);
723 Ok((promoted_key, new_keys, new_child_ids))
724 }
725}
726
727#[cfg(test)]
728mod tests {
729 use super::*;
730
731 #[test]
732 fn test_event_internal_serialize() {
733 let internal_node = EventInternalNode {
735 keys: vec![Position(1000), Position(2000), Position(3000)],
736 child_ids: vec![PageID(100), PageID(200), PageID(300), PageID(400)],
737 };
738
739 let mut serialized = vec![0u8; internal_node.calc_serialized_size()];
741 internal_node.serialize_into(&mut serialized).unwrap();
742
743 assert!(!serialized.is_empty());
745
746 let deserialized = EventInternalNode::from_slice(&serialized)
748 .expect("Failed to deserialize EventInternalNode");
749
750 assert_eq!(internal_node, deserialized);
752
753 assert_eq!(3, deserialized.keys.len());
755 assert_eq!(4, deserialized.child_ids.len());
756
757 assert_eq!(Position(1000), deserialized.keys[0]);
759 assert_eq!(Position(2000), deserialized.keys[1]);
760 assert_eq!(Position(3000), deserialized.keys[2]);
761
762 assert_eq!(PageID(100), deserialized.child_ids[0]);
764 assert_eq!(PageID(200), deserialized.child_ids[1]);
765 assert_eq!(PageID(300), deserialized.child_ids[2]);
766 assert_eq!(PageID(400), deserialized.child_ids[3]);
767 }
768
769 #[test]
770 fn test_event_leaf_serialize_without_uuid() {
771 let leaf_node = EventLeafNode {
773 keys: vec![Position(1000), Position(2000), Position(3000)],
774 values: vec![
775 EventValue::Inline(EventRecord {
776 event_type: "event_type_1".to_string(),
777 data: vec![1, 0, 0, 0], tags: vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()],
779 uuid: None,
780 metadata: Vec::new(),
781 }),
782 EventValue::Inline(EventRecord {
783 event_type: "event_type_2".to_string(),
784 data: vec![2, 0, 0, 0], tags: vec![
786 "tag4".to_string(),
787 "tag5".to_string(),
788 "tag6".to_string(),
789 "tag7".to_string(),
790 ],
791 uuid: None,
792 metadata: Vec::new(),
793 }),
794 EventValue::Inline(EventRecord {
795 event_type: "event_type_3".to_string(),
796 data: vec![3, 0, 0, 0], tags: vec!["tag8".to_string(), "tag9".to_string()],
798 uuid: None,
799 metadata: Vec::new(),
800 }),
801 ],
802 };
803
804 let mut serialized = vec![0u8; leaf_node.calc_serialized_size()];
806 leaf_node.serialize_into(&mut serialized).unwrap();
807
808 assert!(!serialized.is_empty());
810
811 let deserialized =
813 EventLeafNode::from_slice(&serialized).expect("Failed to deserialize EventLeafNode");
814
815 assert_eq!(leaf_node, deserialized);
817
818 assert_eq!(3, deserialized.keys.len());
820 assert_eq!(3, deserialized.values.len());
821
822 assert_eq!(Position(1000), deserialized.keys[0]);
824 assert_eq!(Position(2000), deserialized.keys[1]);
825 assert_eq!(Position(3000), deserialized.keys[2]);
826
827 match &deserialized.values[0] {
829 EventValue::Inline(v) => {
830 assert_eq!("event_type_1", v.event_type);
831 assert_eq!(vec![1, 0, 0, 0], v.data);
832 assert_eq!(
833 vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()],
834 v.tags
835 );
836 assert_eq!(None, v.uuid);
837 }
838 _ => panic!("Expected Inline for first value"),
839 }
840
841 match &deserialized.values[1] {
843 EventValue::Inline(v) => {
844 assert_eq!("event_type_2", v.event_type);
845 assert_eq!(vec![2, 0, 0, 0], v.data);
846 assert_eq!(
847 vec![
848 "tag4".to_string(),
849 "tag5".to_string(),
850 "tag6".to_string(),
851 "tag7".to_string()
852 ],
853 v.tags
854 );
855 assert_eq!(None, v.uuid);
856 }
857 _ => panic!("Expected Inline for second value"),
858 }
859
860 match &deserialized.values[2] {
862 EventValue::Inline(v) => {
863 assert_eq!("event_type_3", v.event_type);
864 assert_eq!(vec![3, 0, 0, 0], v.data);
865 assert_eq!(vec!["tag8".to_string(), "tag9".to_string()], v.tags);
866 assert_eq!(None, v.uuid);
867 }
868 _ => panic!("Expected Inline for third value"),
869 }
870 }
871
872 #[test]
873 fn test_event_leaf_serialize_with_uuid() {
874 let uuid1 = Uuid::new_v4();
876 let uuid2 = Uuid::new_v4();
877 let uuid3 = Uuid::new_v4();
878 let leaf_node = EventLeafNode {
879 keys: vec![Position(1000), Position(2000), Position(3000)],
880 values: vec![
881 EventValue::Inline(EventRecord {
882 event_type: "event_type_1".to_string(),
883 data: vec![1, 0, 0, 0], tags: vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()],
885 uuid: Some(uuid1),
886 metadata: Vec::new(),
887 }),
888 EventValue::Inline(EventRecord {
889 event_type: "event_type_2".to_string(),
890 data: vec![2, 0, 0, 0], tags: vec![
892 "tag4".to_string(),
893 "tag5".to_string(),
894 "tag6".to_string(),
895 "tag7".to_string(),
896 ],
897 uuid: Some(uuid2),
898 metadata: Vec::new(),
899 }),
900 EventValue::Inline(EventRecord {
901 event_type: "event_type_3".to_string(),
902 data: vec![3, 0, 0, 0], tags: vec!["tag8".to_string(), "tag9".to_string()],
904 uuid: Some(uuid3),
905 metadata: Vec::new(),
906 }),
907 ],
908 };
909
910 let mut serialized = vec![0u8; leaf_node.calc_serialized_size()];
912 leaf_node.serialize_into(&mut serialized).unwrap();
913
914 assert!(!serialized.is_empty());
916
917 let deserialized =
919 EventLeafNode::from_slice(&serialized).expect("Failed to deserialize EventLeafNode");
920
921 assert_eq!(leaf_node, deserialized);
923
924 assert_eq!(3, deserialized.keys.len());
926 assert_eq!(3, deserialized.values.len());
927
928 assert_eq!(Position(1000), deserialized.keys[0]);
930 assert_eq!(Position(2000), deserialized.keys[1]);
931 assert_eq!(Position(3000), deserialized.keys[2]);
932
933 match &deserialized.values[0] {
935 EventValue::Inline(v) => {
936 assert_eq!("event_type_1", v.event_type);
937 assert_eq!(vec![1, 0, 0, 0], v.data);
938 assert_eq!(
939 vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()],
940 v.tags
941 );
942 assert_eq!(Some(uuid1), v.uuid);
943 }
944 _ => panic!("Expected Inline for first value"),
945 }
946
947 match &deserialized.values[1] {
949 EventValue::Inline(v) => {
950 assert_eq!("event_type_2", v.event_type);
951 assert_eq!(vec![2, 0, 0, 0], v.data);
952 assert_eq!(
953 vec![
954 "tag4".to_string(),
955 "tag5".to_string(),
956 "tag6".to_string(),
957 "tag7".to_string()
958 ],
959 v.tags
960 );
961 assert_eq!(Some(uuid2), v.uuid);
962 }
963 _ => panic!("Expected Inline for second value"),
964 }
965
966 match &deserialized.values[2] {
968 EventValue::Inline(v) => {
969 assert_eq!("event_type_3", v.event_type);
970 assert_eq!(vec![3, 0, 0, 0], v.data);
971 assert_eq!(vec!["tag8".to_string(), "tag9".to_string()], v.tags);
972 assert_eq!(Some(uuid3), v.uuid);
973 }
974 _ => panic!("Expected Inline for third value"),
975 }
976 }
977
978 #[test]
979 fn test_event_leaf_serialize_with_overflow_single_without_uuid() {
980 let leaf_node = EventLeafNode {
981 keys: vec![Position(111)],
982 values: vec![EventValue::Overflow {
983 event_type: "over_evt".to_string(),
984 data_len: 1234567,
985 tags: vec!["a".to_string(), "b".to_string()],
986 root_id: PageID(123),
987 uuid: None,
988 metadata_len: 0,
989 }],
990 };
991 let mut serialized = vec![0u8; leaf_node.calc_serialized_size()];
993 leaf_node.serialize_into(&mut serialized).unwrap();
994 assert!(!serialized.is_empty());
995 let deserialized = EventLeafNode::from_slice(&serialized)
997 .expect("Failed to deserialize EventLeafNode with overflow");
998 assert_eq!(leaf_node, deserialized);
999
1000 assert_eq!(1, deserialized.keys.len());
1002 assert_eq!(Position(111), deserialized.keys[0]);
1003 assert_eq!(1, deserialized.values.len());
1004 match &deserialized.values[0] {
1005 EventValue::Overflow {
1006 event_type,
1007 data_len,
1008 tags,
1009 root_id,
1010 uuid,
1011 metadata_len,
1012 } => {
1013 assert_eq!("over_evt", event_type);
1014 assert_eq!(1234567, *data_len);
1015 assert_eq!(vec!["a".to_string(), "b".to_string()], *tags);
1016 assert_eq!(PageID(123), *root_id);
1017 assert_eq!(None, *uuid);
1018 assert_eq!(0, *metadata_len);
1019 }
1020 _ => panic!("Expected Overflow variant"),
1021 }
1022 }
1023
1024 #[test]
1025 fn test_event_leaf_serialize_with_overflow_single_with_uuid() {
1026 let uuid1 = Uuid::new_v4();
1027 let leaf_node = EventLeafNode {
1028 keys: vec![Position(111)],
1029 values: vec![EventValue::Overflow {
1030 event_type: "over_evt".to_string(),
1031 data_len: 1234567,
1032 tags: vec!["a".to_string(), "b".to_string()],
1033 root_id: PageID(123),
1034 uuid: Some(uuid1),
1035 metadata_len: 0,
1036 }],
1037 };
1038 let mut serialized = vec![0u8; leaf_node.calc_serialized_size()];
1040 leaf_node.serialize_into(&mut serialized).unwrap();
1041 assert!(!serialized.is_empty());
1042 let deserialized = EventLeafNode::from_slice(&serialized)
1044 .expect("Failed to deserialize EventLeafNode with overflow");
1045 assert_eq!(leaf_node, deserialized);
1046
1047 assert_eq!(1, deserialized.keys.len());
1049 assert_eq!(Position(111), deserialized.keys[0]);
1050 assert_eq!(1, deserialized.values.len());
1051 match &deserialized.values[0] {
1052 EventValue::Overflow {
1053 event_type,
1054 data_len,
1055 tags,
1056 root_id,
1057 uuid,
1058 metadata_len: 0,
1059 } => {
1060 assert_eq!("over_evt", event_type);
1061 assert_eq!(1234567, *data_len);
1062 assert_eq!(vec!["a".to_string(), "b".to_string()], *tags);
1063 assert_eq!(PageID(123), *root_id);
1064 assert_eq!(Some(uuid1), *uuid);
1065 }
1066 _ => panic!("Expected Overflow variant"),
1067 }
1068 }
1069
1070 #[test]
1071 fn test_event_leaf_serialize_mixed_inline_and_overflow() {
1072 let inline = EventValue::Inline(EventRecord {
1073 event_type: "inline_evt".to_string(),
1074 data: vec![1, 2, 3],
1075 tags: vec!["x".to_string()],
1076 uuid: None,
1077 metadata: Vec::new(),
1078 });
1079 let overflow = EventValue::Overflow {
1080 event_type: "overflow_evt".to_string(),
1081 data_len: 9999,
1082 tags: vec!["y".to_string(), "z".to_string()],
1083 root_id: PageID(999),
1084 uuid: None,
1085 metadata_len: 0,
1086 };
1087 let leaf_node = EventLeafNode {
1088 keys: vec![Position(10), Position(20)],
1089 values: vec![inline.clone(), overflow.clone()],
1090 };
1091 let mut serialized = vec![0u8; leaf_node.calc_serialized_size()];
1092 leaf_node.serialize_into(&mut serialized).unwrap();
1093 let deserialized = EventLeafNode::from_slice(&serialized).unwrap();
1094 assert_eq!(leaf_node, deserialized);
1095
1096 match &deserialized.values[0] {
1098 EventValue::Inline(rec) => {
1099 assert_eq!("inline_evt", rec.event_type);
1100 assert_eq!(vec![1, 2, 3], rec.data);
1101 assert_eq!(vec!["x".to_string()], rec.tags);
1102 assert_eq!(None, rec.uuid);
1103 }
1104 _ => panic!("Expected Inline at index 0"),
1105 }
1106 match &deserialized.values[1] {
1107 EventValue::Overflow {
1108 event_type,
1109 data_len,
1110 tags,
1111 root_id,
1112 uuid,
1113 metadata_len,
1114 } => {
1115 assert_eq!("overflow_evt", event_type);
1116 assert_eq!(9999, *data_len);
1117 assert_eq!(vec!["y".to_string(), "z".to_string()], *tags);
1118 assert_eq!(PageID(999), *root_id);
1119 assert_eq!(None, *uuid);
1120 assert_eq!(0, *metadata_len);
1121 }
1122 _ => panic!("Expected Overflow at index 1"),
1123 }
1124 }
1125
1126 #[test]
1127 fn test_metadata_serialize_roundtrip() {
1128 let mut metadata = Vec::new();
1129 metadata.push(("source".to_string(), "web".to_string()));
1130 metadata.push(("correlation_id".to_string(), "abc-123".to_string()));
1131 metadata.push(("empty_value".to_string(), "".to_string()));
1132
1133 let bytes = serialize_metadata(&metadata);
1134 assert_eq!(bytes.len(), metadata_serialized_size(&metadata));
1135
1136 let deserialized = deserialize_metadata(&bytes).unwrap();
1137 assert_eq!(metadata, deserialized);
1138 }
1139
1140 #[test]
1141 fn test_validate_metadata_within_limits_ok() {
1142 let mut metadata = Vec::new();
1143 metadata.push(("k".to_string(), "v".to_string()));
1144 metadata.push(("a".repeat(MAX_METADATA_ENTRY_LEN), "b".to_string()));
1146 metadata.push(("c".to_string(), "d".repeat(MAX_METADATA_ENTRY_LEN)));
1147 assert!(validate_metadata(&metadata).is_ok());
1148 }
1149
1150 #[test]
1175 fn test_validate_tags_rejects_too_many_tags() {
1176 let tags = vec!["tag".to_string(); MAX_TAGS + 1];
1177 match validate_tags(&tags) {
1178 Err(DcbError::InvalidArgument(msg)) => {
1179 assert!(msg.contains("event has"));
1180 assert!(msg.contains("tags, exceeding the maximum"));
1181 }
1182 other => panic!("Expected InvalidArgument, got {other:?}"),
1183 }
1184 }
1185
1186 #[test]
1187 fn test_has_duplicate() {
1188 let mut metadata = Vec::new();
1190 metadata.push(("key1".to_string(), "val1".to_string()));
1191 metadata.push(("key2".to_string(), "val2".to_string()));
1192 assert!(!has_duplicate_metadata_key(&metadata));
1193
1194 metadata.push(("key1".to_string(), "val3".to_string()));
1196 assert!(has_duplicate_metadata_key(&metadata));
1197
1198 let mut large_metadata = Vec::new();
1200 for i in 0..10 {
1201 large_metadata.push((format!("key{i}"), "val".to_string()));
1202 }
1203 assert!(!has_duplicate_metadata_key(&large_metadata));
1204
1205 large_metadata.push(("key5".to_string(), "duplicate".to_string()));
1206 assert!(has_duplicate_metadata_key(&large_metadata));
1207 }
1208
1209 #[test]
1210 fn test_validate_metadata_rejects_duplicates() {
1211 let mut metadata = Vec::new();
1212 metadata.push(("key1".to_string(), "val1".to_string()));
1213 metadata.push(("key1".to_string(), "val2".to_string()));
1214 match validate_metadata(&metadata) {
1215 Err(DcbError::InvalidArgument(msg)) => {
1216 assert!(msg.contains("duplicate keys"));
1217 }
1218 other => panic!("Expected InvalidArgument with duplicate keys message, got {other:?}"),
1219 }
1220 }
1221
1222 #[test]
1223 fn test_validate_metadata_rejects_oversized_value() {
1224 let mut metadata = Vec::new();
1225 metadata.push(("k".to_string(), "v".repeat(MAX_METADATA_ENTRY_LEN + 1)));
1226 match validate_metadata(&metadata) {
1227 Err(DcbError::InvalidArgument(_)) => {}
1228 other => panic!("Expected InvalidArgument, got {other:?}"),
1229 }
1230 }
1231
1232 #[test]
1233 fn test_validate_metadata_rejects_oversized_key() {
1234 let mut metadata = Vec::new();
1235 metadata.push(("k".repeat(MAX_METADATA_ENTRY_LEN + 1), "v".to_string()));
1236 match validate_metadata(&metadata) {
1237 Err(DcbError::InvalidArgument(_)) => {}
1238 other => panic!("Expected InvalidArgument, got {other:?}"),
1239 }
1240 }
1241
1242 #[test]
1243 fn test_metadata_serialize_roundtrip_at_max_entry_len() {
1244 let mut metadata = Vec::new();
1246 metadata.push(("k".repeat(MAX_METADATA_ENTRY_LEN), "v".to_string()));
1247 metadata.push(("k2".to_string(), "v".repeat(MAX_METADATA_ENTRY_LEN)));
1248 let bytes = serialize_metadata(&metadata);
1249 assert_eq!(bytes.len(), metadata_serialized_size(&metadata));
1250 assert_eq!(metadata, deserialize_metadata(&bytes).unwrap());
1251 }
1252
1253 #[test]
1254 fn test_empty_metadata_serialize_roundtrip() {
1255 let metadata: Vec<(String, String)> = Vec::new();
1256 let bytes = serialize_metadata(&metadata);
1257 assert_eq!(bytes.len(), 2);
1259 assert_eq!(metadata, deserialize_metadata(&bytes).unwrap());
1260 }
1261
1262 #[test]
1263 fn test_event_leaf_serialize_inline_with_metadata() {
1264 let mut md1 = Vec::new();
1265 md1.push(("source".to_string(), "ingest".to_string()));
1266 md1.push(("schema".to_string(), "v2".to_string()));
1267
1268 let mut md3 = Vec::new();
1269 md3.push(("trace".to_string(), "deadbeef".to_string()));
1270
1271 let uuid2 = Uuid::new_v4();
1272 let leaf_node = EventLeafNode {
1273 keys: vec![Position(10), Position(20), Position(30)],
1274 values: vec![
1275 EventValue::Inline(EventRecord {
1277 event_type: "with_md".to_string(),
1278 data: vec![1, 2, 3, 4],
1279 tags: vec!["tag1".to_string()],
1280 uuid: None,
1281 metadata: md1.clone(),
1282 }),
1283 EventValue::Inline(EventRecord {
1285 event_type: "uuid_and_md".to_string(),
1286 data: vec![5, 6],
1287 tags: vec!["tag2".to_string(), "tag3".to_string()],
1288 uuid: Some(uuid2),
1289 metadata: md3.clone(),
1290 }),
1291 EventValue::Inline(EventRecord {
1293 event_type: "no_md".to_string(),
1294 data: vec![7],
1295 tags: vec![],
1296 uuid: None,
1297 metadata: Vec::new(),
1298 }),
1299 ],
1300 };
1301
1302 let mut serialized = vec![0u8; leaf_node.calc_serialized_size()];
1303 let written = leaf_node.serialize_into(&mut serialized).unwrap();
1304 assert_eq!(written, serialized.len());
1305
1306 let deserialized =
1307 EventLeafNode::from_slice(&serialized).expect("Failed to deserialize EventLeafNode");
1308 assert_eq!(leaf_node, deserialized);
1309
1310 match &deserialized.values[0] {
1311 EventValue::Inline(rec) => assert_eq!(md1, rec.metadata),
1312 _ => panic!("Expected Inline at index 0"),
1313 }
1314 match &deserialized.values[1] {
1315 EventValue::Inline(rec) => {
1316 assert_eq!(Some(uuid2), rec.uuid);
1317 assert_eq!(md3, rec.metadata);
1318 }
1319 _ => panic!("Expected Inline at index 1"),
1320 }
1321 match &deserialized.values[2] {
1322 EventValue::Inline(rec) => assert!(rec.metadata.is_empty()),
1323 _ => panic!("Expected Inline at index 2"),
1324 }
1325 }
1326
1327 #[test]
1328 fn test_event_overflow_node_serialize_roundtrip() {
1329 let node = EventOverflowNode {
1330 next: PageID(77),
1331 data: vec![7, 8, 9, 10],
1332 };
1333 let mut ser = vec![0u8; node.calc_serialized_size()];
1334 node.serialize_into(&mut ser).unwrap();
1335 assert_eq!(8 + 4, ser.len()); let de = EventOverflowNode::from_slice(&ser).unwrap();
1337 assert_eq!(node, de);
1338 assert_eq!(PageID(77), de.next);
1339 assert_eq!(vec![7, 8, 9, 10], de.data);
1340 }
1341}