use crate::{data_pointer::DataPointer, errors::Error};
#[derive(Debug)]
pub enum EntryValue {
Boolean(bool),
Byte(u8),
Char(char),
Short(i16),
Int(i32),
Long(i64),
Float(f32),
Double(f64),
BooleanVec(Vec<bool>),
String(String),
CharVec(Vec<char>),
ShortVec(Vec<i16>),
IntVec(Vec<i32>),
LongVec(Vec<i64>),
FloatVec(Vec<f32>),
DoubleVec(Vec<f64>),
NotSet,
}
impl EntryValue {
pub(crate) fn new(pointer: &DataPointer) -> Result<Self, Error> {
Ok(match pointer {
DataPointer::Boolean(ptr) => EntryValue::Boolean(ptr.read() == 0),
DataPointer::Byte(ptr) => EntryValue::Byte(ptr.read()),
DataPointer::Char(ptr) => EntryValue::Char(ptr.read() as char),
DataPointer::Short(ptr) => EntryValue::Short(ptr.read_i16()?),
DataPointer::Int(ptr) => EntryValue::Int(ptr.read_i32()?),
DataPointer::Long(ptr) => EntryValue::Long(ptr.read_i64()?),
DataPointer::Float(ptr) => EntryValue::Float(ptr.read_f32()?),
DataPointer::Double(ptr) => EntryValue::Double(ptr.read_f64()?),
DataPointer::BooleanVec(ptr, length) => {
EntryValue::BooleanVec(ptr.read_booleans(*length)?)
}
DataPointer::ByteVec(ptr, length) => EntryValue::String(ptr.read_string(*length)?),
DataPointer::CharVec(ptr, length) => EntryValue::CharVec(ptr.read_n(*length)?),
DataPointer::ShortVec(ptr, length) => EntryValue::ShortVec(ptr.read_n_i16(*length)?),
DataPointer::IntVec(ptr, length) => EntryValue::IntVec(ptr.read_n_i32(*length)?),
DataPointer::LongVec(ptr, length) => EntryValue::LongVec(ptr.read_n_i64(*length)?),
DataPointer::FloatVec(ptr, length) => EntryValue::FloatVec(ptr.read_n_f32(*length)?),
DataPointer::DoubleVec(ptr, length) => EntryValue::DoubleVec(ptr.read_n_f64(*length)?),
})
}
}
#[cfg(test)]
mod tests {
use crate::{
data_pointer::DataPointer,
entry_value::EntryValue,
perf_data::{DataType, Endianness},
safish_pointer::SafishPointer,
};
#[test]
fn new_boolean_false_returns_boolean_false() {
let data = 0u8; let ptr = SafishPointer::new(&data as *const u8, 1, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Boolean, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Boolean(true))); }
#[test]
fn new_boolean_true_returns_boolean_true() {
let data = 1u8; let ptr = SafishPointer::new(&data as *const u8, 1, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Boolean, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Boolean(false))); }
#[test]
fn new_byte_returns_byte() {
let data = 42u8;
let ptr = SafishPointer::new(&data as *const u8, 1, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Byte, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Byte(42)));
}
#[test]
fn new_char_returns_char() {
let data = 'A';
let ptr = SafishPointer::new(&data as *const char, 4, Endianness::BigEndian).unwrap();
let data_pointer =
DataPointer::new_scalar(&DataType::Char, ptr.convert().unwrap()).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Char('A')));
}
#[test]
fn new_short_returns_short() {
let data = (1234i16).to_be_bytes();
let ptr = SafishPointer::new(data.as_ptr(), 2, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Short, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Short(1234)));
}
#[test]
fn new_int_returns_int() {
let data = (123456i32).to_be_bytes();
let ptr = SafishPointer::new(data.as_ptr(), 4, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Int, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Int(123456)));
}
#[test]
fn new_long_returns_long() {
let data = (1234567890i64).to_be_bytes();
let ptr = SafishPointer::new(data.as_ptr(), 8, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Long, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Long(1234567890)));
}
#[test]
fn new_float_returns_float() {
let data = (3.14159f32).to_be_bytes();
let ptr = SafishPointer::new(data.as_ptr(), 4, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Float, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Float(3.14159)));
}
#[test]
fn new_double_returns_double() {
let data = (2.718281828459045f64).to_be_bytes();
let ptr = SafishPointer::new(data.as_ptr(), 8, Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Double, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Double(2.718281828459045)));
}
#[test]
fn new_with_little_endian_works() {
let data = (1234i32).to_le_bytes();
let ptr = SafishPointer::new(data.as_ptr(), 4, Endianness::LittleEndian).unwrap();
let data_pointer = DataPointer::new_scalar(&DataType::Int, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
assert!(matches!(result, EntryValue::Int(1234)));
}
#[test]
fn new_boolean_returns_boolean_vec() {
let data = [0u8, 1u8, 0u8, 1u8];
let ptr = SafishPointer::new(data.as_ptr(), data.len(), Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Boolean, 4, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = vec![true, false, true, false];
match result {
EntryValue::BooleanVec(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_byte_returns_string() {
let data = "Hello".as_bytes();
let ptr = SafishPointer::new(data.as_ptr(), data.len(), Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Byte, 5, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = "Hello".to_string();
match result {
EntryValue::String(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_char_returns_char_vec() {
let data = ['A', 'B', 'C'];
let ptr = SafishPointer::new(
data.as_ptr() as *const u8,
data.len() * size_of::<char>(),
Endianness::BigEndian,
)
.unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Char, 3, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = vec!['A', 'B', 'C'];
match result {
EntryValue::CharVec(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_short_returns_short_vec() {
let values = [1i16, 2, 3, 4, 5];
let data: Vec<u8> = values.iter().flat_map(|&v| v.to_be_bytes()).collect();
let ptr = SafishPointer::new(data.as_ptr(), data.len(), Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Short, 5, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = vec![1, 2, 3, 4, 5];
match result {
EntryValue::ShortVec(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_int_returns_int_vec() {
let values = [10i32, 20, 30, 40];
let data: Vec<u8> = values.iter().flat_map(|&v| v.to_be_bytes()).collect();
let ptr = SafishPointer::new(data.as_ptr(), data.len(), Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Int, 4, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = vec![10, 20, 30, 40];
match result {
EntryValue::IntVec(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_long_returns_long_vec() {
let values = [100i64, 200, 300];
let data: Vec<u8> = values.iter().flat_map(|&v| v.to_be_bytes()).collect();
let ptr = SafishPointer::new(data.as_ptr(), data.len(), Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Long, 3, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = vec![100, 200, 300];
match result {
EntryValue::LongVec(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_float_returns_float_vec() {
let values = [1.1f32, 2.2, 3.3];
let data: Vec<u8> = values.iter().flat_map(|&v| v.to_be_bytes()).collect();
let ptr = SafishPointer::new(data.as_ptr(), data.len(), Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Float, 3, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = vec![1.1, 2.2, 3.3];
match result {
EntryValue::FloatVec(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_double_returns_double_vec() {
let values = [1.111f64, 2.222];
let data: Vec<u8> = values.iter().flat_map(|&v| v.to_be_bytes()).collect();
let ptr = SafishPointer::new(data.as_ptr(), data.len(), Endianness::BigEndian).unwrap();
let data_pointer = DataPointer::new_vector(&DataType::Double, 2, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = vec![1.111, 2.222];
match result {
EntryValue::DoubleVec(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
#[test]
fn new_byte_with_null_terminated_string() {
let data = "Hello\0World".as_bytes();
let ptr = SafishPointer::new(data.as_ptr(), 5, Endianness::BigEndian).unwrap(); let data_pointer = DataPointer::new_vector(&DataType::Byte, 5, ptr).unwrap();
let result = EntryValue::new(&data_pointer).unwrap();
let expected = "Hello".to_string();
match result {
EntryValue::String(content) => assert_eq!(content, expected),
_ => assert!(false),
}
}
}