use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use chrono::{DateTime, Utc};
use ordered_float::OrderedFloat;
use crate::static_btree::error::Result;
use crate::FixedStringKey;
use crate::Key;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::io::{Read, Write};
use std::mem;
pub type Offset = u64;
pub const OFFSET_SIZE: usize = mem::size_of::<Offset>();
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Entry<K: Key> {
pub key: K,
pub offset: Offset, }
impl<K: Key> Entry<K> {
const OFFSET_SIZE: usize = mem::size_of::<Offset>();
pub const SERIALIZED_SIZE: usize = K::SERIALIZED_SIZE + Self::OFFSET_SIZE;
pub fn new(key: K, offset: Offset) -> Self {
Self { key, offset }
}
pub fn write_to<W: Write>(&self, writer: &mut W) -> Result<usize> {
let mut written_bytes = 0;
written_bytes += self.key.write_to(writer)?;
writer.write_u64::<LittleEndian>(self.offset)?;
written_bytes += Self::OFFSET_SIZE;
Ok(written_bytes)
}
pub fn from_reader<R: Read>(reader: &mut R) -> Result<Self> {
let key = K::read_from(reader)?;
let offset = reader.read_u64::<LittleEndian>()?;
Ok(Entry { key, offset })
}
pub fn from_bytes(raw: &[u8]) -> Result<Self> {
let key = K::from_bytes(&raw[0..K::SERIALIZED_SIZE])?;
let offset = Offset::from_bytes(&raw[K::SERIALIZED_SIZE..])?;
Ok(Entry { key, offset })
}
pub fn key_size() -> usize {
K::SERIALIZED_SIZE
}
}
impl<K: Key> PartialOrd for Entry<K> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.key.partial_cmp(&other.key)
}
}
impl<K: Key> Ord for Entry<K> {
fn cmp(&self, other: &Self) -> Ordering {
self.key.cmp(&other.key)
}
}
pub enum TypedEntry {
StringKey20(Entry<FixedStringKey<20>>),
StringKey50(Entry<FixedStringKey<50>>),
StringKey100(Entry<FixedStringKey<100>>),
Int32(Entry<i32>),
Int64(Entry<i64>),
UInt32(Entry<u32>),
UInt64(Entry<u64>),
Float32(Entry<OrderedFloat<f32>>),
Float64(Entry<OrderedFloat<f64>>),
Bool(Entry<bool>),
DateTime(Entry<DateTime<Utc>>),
}
#[cfg(test)]
mod tests {
use super::*;
use crate::static_btree::error::Error;
use crate::Key;
use std::io::Cursor;
#[test]
fn test_entry_serialization_deserialization() {
let entry = Entry {
key: 12345,
offset: 9876543210,
};
let mut buffer = Vec::new();
entry.write_to(&mut buffer).expect("write should succeed");
assert_eq!(
buffer.len(),
i32::SERIALIZED_SIZE + mem::size_of::<Offset>()
);
assert_eq!(buffer.len(), Entry::<i32>::SERIALIZED_SIZE);
let mut cursor = Cursor::new(buffer);
let deserialized_entry =
Entry::<i32>::from_reader(&mut cursor).expect("read should succeed");
assert_eq!(entry, deserialized_entry);
}
#[test]
fn test_entry_ordering() {
let entry1 = Entry {
key: 10,
offset: 100,
};
let entry2 = Entry {
key: 20,
offset: 50,
};
let entry3 = Entry {
key: 10,
offset: 200,
};
assert!(entry1 < entry2);
assert!(entry2 > entry1);
assert_eq!(entry1.cmp(&entry3), Ordering::Equal);
assert_eq!(entry1.partial_cmp(&entry3), Some(Ordering::Equal));
}
#[test]
fn test_entry_read_error_short_read() {
let mut short_buffer = vec![0u8; Entry::<i32>::SERIALIZED_SIZE - 1]; let mut cursor = Cursor::new(&mut short_buffer);
let result = Entry::<i32>::from_reader(&mut cursor); assert!(result.is_err());
match result.err().unwrap() {
Error::IoError(e) => assert_eq!(e.kind(), std::io::ErrorKind::UnexpectedEof),
_ => panic!("expected io error"),
}
}
}