#[derive(Debug, Clone, Copy)]
pub struct Entry<'a> {
bytes: &'a [u8],
length: u32,
id: u32,
}
impl<'a> Default for Entry<'a> {
fn default() -> Self {
Self::new()
}
}
impl<'a> Entry<'a> {
pub fn new() -> Self {
Entry {
bytes: &[],
length: 0,
id: 0,
}
}
#[inline]
pub fn get(&self, i: usize) -> u8 {
assert!(i < self.length as usize, "Index out of bounds");
self.bytes[self.length as usize - 1 - i]
}
pub fn set_str(&mut self, bytes: &'a [u8]) {
assert!(bytes.len() <= u32::MAX as usize, "String too long");
self.bytes = bytes;
self.length = bytes.len() as u32;
}
#[inline]
pub fn set_id(&mut self, id: usize) {
assert!(id <= u32::MAX as usize, "ID too large");
self.id = id as u32;
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[..self.length as usize]
}
#[inline]
pub fn length(&self) -> usize {
self.length as usize
}
#[inline]
pub fn id(&self) -> usize {
self.id as usize
}
}
#[derive(Debug, Clone, Copy)]
pub struct StringComparer;
impl StringComparer {
pub fn compare(lhs: &Entry<'_>, rhs: &Entry<'_>) -> bool {
for i in 0..lhs.length() {
if i == rhs.length() {
return true;
}
if lhs.get(i) != rhs.get(i) {
return lhs.get(i) > rhs.get(i);
}
}
lhs.length() > rhs.length()
}
}
#[derive(Debug, Clone, Copy)]
pub struct IDComparer;
impl IDComparer {
pub fn compare(lhs: &Entry<'_>, rhs: &Entry<'_>) -> bool {
lhs.id < rhs.id
}
}
impl<'a> crate::grimoire::algorithm::sort::Sortable for Entry<'a> {
fn get(&self, index: usize) -> Option<u8> {
if index < self.length() {
Some(Entry::get(self, index))
} else {
None
}
}
fn length(&self) -> usize {
Entry::length(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_entry_new() {
let entry = Entry::new();
assert_eq!(entry.length(), 0);
assert_eq!(entry.id(), 0);
}
#[test]
fn test_entry_default() {
let entry = Entry::default();
assert_eq!(entry.length(), 0);
assert_eq!(entry.id(), 0);
}
#[test]
fn test_entry_set_str() {
let data = b"hello";
let mut entry = Entry::new();
entry.set_str(data);
assert_eq!(entry.length(), 5);
assert_eq!(entry.as_bytes(), b"hello");
}
#[test]
fn test_entry_reverse_indexing() {
let data = b"hello";
let mut entry = Entry::new();
entry.set_str(data);
assert_eq!(entry.get(0), b'o');
assert_eq!(entry.get(1), b'l');
assert_eq!(entry.get(2), b'l');
assert_eq!(entry.get(3), b'e');
assert_eq!(entry.get(4), b'h');
}
#[test]
fn test_entry_set_id() {
let data = b"test";
let mut entry = Entry::new();
entry.set_str(data);
entry.set_id(42);
assert_eq!(entry.id(), 42);
}
#[test]
fn test_entry_clone() {
let data = b"test";
let mut entry1 = Entry::new();
entry1.set_str(data);
entry1.set_id(10);
let entry2 = entry1;
assert_eq!(entry2.length(), 4);
assert_eq!(entry2.id(), 10);
assert_eq!(entry2.get(0), b't');
}
#[test]
fn test_string_comparer_equal_length() {
let data1 = b"apple";
let data2 = b"zebra";
let mut entry1 = Entry::new();
let mut entry2 = Entry::new();
entry1.set_str(data1);
entry2.set_str(data2);
let result = StringComparer::compare(&entry1, &entry2);
assert!(result == StringComparer::compare(&entry1, &entry2));
}
#[test]
fn test_string_comparer_different_length() {
let data1 = b"hello";
let data2 = b"hi";
let mut entry1 = Entry::new();
let mut entry2 = Entry::new();
entry1.set_str(data1);
entry2.set_str(data2);
let result = StringComparer::compare(&entry1, &entry2);
assert!(result);
}
#[test]
fn test_string_comparer_prefix() {
let data1 = b"hello";
let data2 = b"helloworld";
let mut entry1 = Entry::new();
let mut entry2 = Entry::new();
entry1.set_str(data1);
entry2.set_str(data2);
let result = StringComparer::compare(&entry1, &entry2);
assert!(result == StringComparer::compare(&entry1, &entry2));
}
#[test]
fn test_id_comparer() {
let data = b"test";
let mut entry1 = Entry::new();
let mut entry2 = Entry::new();
entry1.set_str(data);
entry2.set_str(data);
entry1.set_id(10);
entry2.set_id(20);
assert!(IDComparer::compare(&entry1, &entry2));
assert!(!IDComparer::compare(&entry2, &entry1));
}
#[test]
fn test_id_comparer_equal() {
let data = b"test";
let mut entry1 = Entry::new();
let mut entry2 = Entry::new();
entry1.set_str(data);
entry2.set_str(data);
entry1.set_id(10);
entry2.set_id(10);
assert!(!IDComparer::compare(&entry1, &entry2));
assert!(!IDComparer::compare(&entry2, &entry1));
}
#[test]
fn test_entry_as_bytes() {
let data = b"rust";
let mut entry = Entry::new();
entry.set_str(data);
assert_eq!(entry.as_bytes(), b"rust");
}
#[test]
fn test_entry_empty_string() {
let data = b"";
let mut entry = Entry::new();
entry.set_str(data);
assert_eq!(entry.length(), 0);
assert_eq!(entry.as_bytes(), b"");
}
#[test]
fn test_entry_max_id() {
let data = b"test";
let mut entry = Entry::new();
entry.set_str(data);
entry.set_id(u32::MAX as usize);
assert_eq!(entry.id(), u32::MAX as usize);
}
#[test]
#[should_panic(expected = "Index out of bounds")]
fn test_entry_get_out_of_bounds() {
let data = b"hi";
let mut entry = Entry::new();
entry.set_str(data);
entry.get(2); }
}