#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum XRefEntryType {
Free,
Uncompressed,
Compressed,
Custom(u8),
}
impl XRefEntryType {
pub fn from_value(value: u64) -> Self {
match value {
0 => XRefEntryType::Free,
1 => XRefEntryType::Uncompressed,
2 => XRefEntryType::Compressed,
n if n <= 255 => XRefEntryType::Custom(n as u8),
_ => XRefEntryType::Free, }
}
pub fn is_in_use(&self) -> bool {
match self {
XRefEntryType::Free => false,
XRefEntryType::Uncompressed => true,
XRefEntryType::Compressed => true,
XRefEntryType::Custom(_) => true,
}
}
pub fn to_value(&self) -> u8 {
match self {
XRefEntryType::Free => 0,
XRefEntryType::Uncompressed => 1,
XRefEntryType::Compressed => 2,
XRefEntryType::Custom(n) => *n,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct XRefEntryInfo {
pub entry_type: XRefEntryType,
pub field2: u64,
pub field3: u64,
}
impl XRefEntryInfo {
pub fn new(entry_type: XRefEntryType, field2: u64, field3: u64) -> Self {
Self {
entry_type,
field2,
field3,
}
}
pub fn get_offset(&self) -> Option<u64> {
match self.entry_type {
XRefEntryType::Uncompressed => Some(self.field2),
_ => None,
}
}
pub fn get_generation(&self) -> u16 {
match self.entry_type {
XRefEntryType::Free | XRefEntryType::Uncompressed => self.field3 as u16,
_ => 0,
}
}
pub fn get_compressed_info(&self) -> Option<(u32, u32)> {
match self.entry_type {
XRefEntryType::Compressed => Some((self.field2 as u32, self.field3 as u32)),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_xref_entry_type_from_value() {
assert_eq!(XRefEntryType::from_value(0), XRefEntryType::Free);
assert_eq!(XRefEntryType::from_value(1), XRefEntryType::Uncompressed);
assert_eq!(XRefEntryType::from_value(2), XRefEntryType::Compressed);
assert_eq!(XRefEntryType::from_value(53), XRefEntryType::Custom(53));
assert_eq!(XRefEntryType::from_value(255), XRefEntryType::Custom(255));
assert_eq!(XRefEntryType::from_value(256), XRefEntryType::Free);
}
#[test]
fn test_is_in_use() {
assert!(!XRefEntryType::Free.is_in_use());
assert!(XRefEntryType::Uncompressed.is_in_use());
assert!(XRefEntryType::Compressed.is_in_use());
assert!(XRefEntryType::Custom(53).is_in_use());
}
#[test]
fn test_entry_info() {
let info = XRefEntryInfo::new(XRefEntryType::Uncompressed, 1234, 5);
assert_eq!(info.get_offset(), Some(1234));
assert_eq!(info.get_generation(), 5);
assert_eq!(info.get_compressed_info(), None);
let compressed = XRefEntryInfo::new(XRefEntryType::Compressed, 10, 20);
assert_eq!(compressed.get_offset(), None);
assert_eq!(compressed.get_generation(), 0);
assert_eq!(compressed.get_compressed_info(), Some((10, 20)));
}
#[test]
fn test_to_value() {
assert_eq!(XRefEntryType::Free.to_value(), 0);
assert_eq!(XRefEntryType::Uncompressed.to_value(), 1);
assert_eq!(XRefEntryType::Compressed.to_value(), 2);
assert_eq!(XRefEntryType::Custom(53).to_value(), 53);
assert_eq!(XRefEntryType::Custom(255).to_value(), 255);
}
#[test]
fn test_free_entry_info() {
let free = XRefEntryInfo::new(XRefEntryType::Free, 100, 65535);
assert_eq!(free.get_offset(), None);
assert_eq!(free.get_generation(), 65535);
assert_eq!(free.get_compressed_info(), None);
}
#[test]
fn test_custom_entry_info() {
let custom = XRefEntryInfo::new(XRefEntryType::Custom(99), 500, 10);
assert_eq!(custom.get_offset(), None);
assert_eq!(custom.get_generation(), 0);
assert_eq!(custom.get_compressed_info(), None);
}
}