use zero_mysql::ref_row::{FixedWireSize, I16LE, I32LE, I64LE, U16LE, U32LE, U64LE};
use zerocopy::{FromBytes, Immutable, KnownLayout};
include!("common/check_eq.rs");
include!("common/check_err.rs");
#[test]
fn fixed_wire_size_primitives() -> Result<(), Box<dyn std::error::Error>> {
check_eq!(<i8 as FixedWireSize>::WIRE_SIZE, 1);
check_eq!(<u8 as FixedWireSize>::WIRE_SIZE, 1);
check_eq!(<I16LE as FixedWireSize>::WIRE_SIZE, 2);
check_eq!(<U16LE as FixedWireSize>::WIRE_SIZE, 2);
check_eq!(<I32LE as FixedWireSize>::WIRE_SIZE, 4);
check_eq!(<U32LE as FixedWireSize>::WIRE_SIZE, 4);
check_eq!(<I64LE as FixedWireSize>::WIRE_SIZE, 8);
check_eq!(<U64LE as FixedWireSize>::WIRE_SIZE, 8);
Ok(())
}
#[test]
fn little_endian_parsing() -> Result<(), Box<dyn std::error::Error>> {
let data1: [u8; 4] = [0x78, 0x56, 0x34, 0x12];
let value1: &I32LE = FromBytes::ref_from_bytes(&data1).unwrap();
check_eq!(value1.get(), 0x12345678);
let data2: [u8; 8] = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
let value2: &I64LE = FromBytes::ref_from_bytes(&data2).unwrap();
check_eq!(value2.get(), 0x0807060504030201);
Ok(())
}
#[test]
fn packed_struct() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Debug, FromBytes, KnownLayout, Immutable)]
#[repr(C, packed)]
struct TestRow {
a: I32LE,
b: I64LE,
c: I16LE,
}
check_eq!(std::mem::size_of::<TestRow>(), 14);
let mut data = [0u8; 14];
data[0..4].copy_from_slice(&42_i32.to_le_bytes());
data[4..12].copy_from_slice(&12345_i64.to_le_bytes());
data[12..14].copy_from_slice(&(-100_i16).to_le_bytes());
let row: &TestRow = FromBytes::ref_from_bytes(&data).unwrap();
check_eq!(row.a.get(), 42);
check_eq!(row.b.get(), 12345);
check_eq!(row.c.get(), -100);
Ok(())
}
#[test]
fn packed_alignment() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Debug, FromBytes, KnownLayout, Immutable)]
#[repr(C, packed)]
struct MixedRow {
a: u8,
b: I64LE,
c: u8,
}
check_eq!(std::mem::size_of::<MixedRow>(), 10);
check_eq!(std::mem::align_of::<MixedRow>(), 1);
Ok(())
}
#[test]
fn unsigned_integers() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Debug, FromBytes, KnownLayout, Immutable)]
#[repr(C, packed)]
struct UnsignedRow {
a: U16LE,
b: U32LE,
c: U64LE,
}
let mut data = [0u8; 14];
data[0..2].copy_from_slice(&0xFFFF_u16.to_le_bytes());
data[2..6].copy_from_slice(&0xDEADBEEF_u32.to_le_bytes());
data[6..14].copy_from_slice(&0xCAFEBABEDEADC0DE_u64.to_le_bytes());
let row: &UnsignedRow = FromBytes::ref_from_bytes(&data).unwrap();
check_eq!(row.a.get(), 0xFFFF);
check_eq!(row.b.get(), 0xDEADBEEF);
check_eq!(row.c.get(), 0xCAFEBABEDEADC0DE);
Ok(())
}
#[test]
fn single_byte_types() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Debug, FromBytes, KnownLayout, Immutable)]
#[repr(C, packed)]
struct ByteRow {
signed: i8,
unsigned: u8,
}
let data: [u8; 2] = [0xFF, 0xFF];
let row: &ByteRow = FromBytes::ref_from_bytes(&data).unwrap();
check_eq!(row.signed, -1);
check_eq!(row.unsigned, 255);
Ok(())
}
#[test]
fn size_validation() -> Result<(), Box<dyn std::error::Error>> {
#[derive(Debug, FromBytes, KnownLayout, Immutable)]
#[repr(C, packed)]
struct TestRow {
a: I32LE,
b: I64LE,
}
let data1 = [0u8; 11];
let _err = check_err!(I32LE::ref_from_bytes(&data1[..3]));
let data2 = [0u8; 12];
<TestRow as FromBytes>::ref_from_bytes(&data2).unwrap();
let data3 = [0u8; 20];
<TestRow as FromBytes>::ref_from_bytes(&data3[..12]).unwrap();
Ok(())
}