fcb_core/static_btree/
entry.rs1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use chrono::{DateTime, Utc};
3use ordered_float::OrderedFloat;
4
5use crate::static_btree::error::Result;
6use crate::FixedStringKey;
7use crate::Key;
8use std::cmp::Ordering;
9use std::fmt::Debug;
10use std::io::{Read, Write};
11use std::mem;
12
13pub type Offset = u64;
18
19pub const OFFSET_SIZE: usize = mem::size_of::<Offset>();
21
22#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct Entry<K: Key> {
26 pub key: K,
28 pub offset: Offset, }
31
32impl<K: Key> Entry<K> {
34 const OFFSET_SIZE: usize = mem::size_of::<Offset>();
36 pub const SERIALIZED_SIZE: usize = K::SERIALIZED_SIZE + Self::OFFSET_SIZE;
38
39 pub fn new(key: K, offset: Offset) -> Self {
40 Self { key, offset }
41 }
42
43 pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<usize> {
46 let mut written_bytes = 0;
47 written_bytes += self.key.write_to(writer)?;
48
49 writer.write_u64::<LittleEndian>(self.offset)?;
50 written_bytes += Self::OFFSET_SIZE;
51 Ok(written_bytes)
52 }
53
54 pub fn from_reader<R: Read>(reader: &mut R) -> Result<Self> {
57 let key = K::read_from(reader)?;
58 let offset = reader.read_u64::<LittleEndian>()?;
59 Ok(Entry { key, offset })
60 }
61
62 pub fn from_bytes(raw: &[u8]) -> Result<Self> {
63 let key = K::from_bytes(&raw[0..K::SERIALIZED_SIZE])?;
64 let offset = Offset::from_bytes(&raw[K::SERIALIZED_SIZE..])?;
65 Ok(Entry { key, offset })
66 }
67
68 pub fn key_size() -> usize {
69 K::SERIALIZED_SIZE
70 }
71}
72
73impl<K: Key> PartialOrd for Entry<K> {
75 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
76 self.key.partial_cmp(&other.key)
77 }
78}
79
80impl<K: Key> Ord for Entry<K> {
81 fn cmp(&self, other: &Self) -> Ordering {
82 self.key.cmp(&other.key)
83 }
84}
85
86pub enum TypedEntry {
87 StringKey20(Entry<FixedStringKey<20>>),
88 StringKey50(Entry<FixedStringKey<50>>),
89 StringKey100(Entry<FixedStringKey<100>>),
90 Int32(Entry<i32>),
91 Int64(Entry<i64>),
92 UInt32(Entry<u32>),
93 UInt64(Entry<u64>),
94 Float32(Entry<OrderedFloat<f32>>),
95 Float64(Entry<OrderedFloat<f64>>),
96 Bool(Entry<bool>),
97 DateTime(Entry<DateTime<Utc>>),
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use crate::static_btree::error::Error;
104 use crate::Key;
105 use std::io::Cursor;
106
107 #[test]
108 fn test_entry_serialization_deserialization() {
109 let entry = Entry {
110 key: 12345,
112 offset: 9876543210,
113 };
114
115 let mut buffer = Vec::new();
116 entry.write_to(&mut buffer).expect("write should succeed");
117
118 assert_eq!(
119 buffer.len(),
120 i32::SERIALIZED_SIZE + mem::size_of::<Offset>()
121 );
122 assert_eq!(buffer.len(), Entry::<i32>::SERIALIZED_SIZE); let mut cursor = Cursor::new(buffer);
125 let deserialized_entry =
126 Entry::<i32>::from_reader(&mut cursor).expect("read should succeed"); assert_eq!(entry, deserialized_entry);
129 }
130
131 #[test]
132 fn test_entry_ordering() {
133 let entry1 = Entry {
134 key: 10,
136 offset: 100,
137 };
138 let entry2 = Entry {
139 key: 20,
141 offset: 50,
142 };
143 let entry3 = Entry {
144 key: 10,
146 offset: 200,
147 };
148
149 assert!(entry1 < entry2);
150 assert!(entry2 > entry1);
151 assert_eq!(entry1.cmp(&entry3), Ordering::Equal);
152 assert_eq!(entry1.partial_cmp(&entry3), Some(Ordering::Equal));
153 }
154
155 #[test]
156 fn test_entry_read_error_short_read() {
157 let mut short_buffer = vec![0u8; Entry::<i32>::SERIALIZED_SIZE - 1]; let mut cursor = Cursor::new(&mut short_buffer);
159 let result = Entry::<i32>::from_reader(&mut cursor); assert!(result.is_err());
161 match result.err().unwrap() {
162 Error::IoError(e) => assert_eq!(e.kind(), std::io::ErrorKind::UnexpectedEof),
163 _ => panic!("expected io error"),
164 }
165 }
166}