use crate::ibverbs::memory::MemoryRegion;
use ibverbs_sys::ibv_sge;
use std::marker::PhantomData;
use thiserror::Error;
#[derive(Copy, Clone, Debug)]
#[repr(transparent)]
pub struct GatherElement<'a> {
sge: ibv_sge,
_mr_lifetime: PhantomData<&'a MemoryRegion>,
_data_lifetime: PhantomData<&'a [u8]>,
}
#[derive(Debug)]
#[repr(transparent)]
pub struct ScatterElement<'a> {
sge: ibv_sge,
_mr_lifetime: PhantomData<&'a MemoryRegion>,
_data_lifetime: PhantomData<&'a mut [u8]>,
}
#[derive(Debug, Error)]
pub enum ScatterGatherElementError {
#[error("maximum length of mr slice exceeded")]
SliceTooBig,
#[error("slice is not within the bounds of the mr")]
SliceNotWithinBounds,
}
impl<'a> GatherElement<'a> {
pub fn new(mr: &'a MemoryRegion, data: &'a [u8]) -> Self {
debug_assert!(data.len() <= u32::MAX as usize);
debug_assert!(mr.encloses_slice(data));
Self::new_unchecked(mr, data)
}
pub fn new_checked(
mr: &'a MemoryRegion,
data: &'a [u8],
) -> Result<Self, ScatterGatherElementError> {
if data.len() > u32::MAX as usize {
return Err(ScatterGatherElementError::SliceTooBig);
}
if !mr.encloses_slice(data) {
return Err(ScatterGatherElementError::SliceNotWithinBounds);
}
Ok(Self::new_unchecked(mr, data))
}
#[allow(clippy::cast_possible_truncation)]
pub fn new_unchecked(mr: &'a MemoryRegion, data: &'a [u8]) -> Self {
Self {
sge: ibv_sge {
addr: data.as_ptr() as u64,
length: data.len() as u32,
lkey: mr.lkey(),
},
_mr_lifetime: PhantomData::<&'a MemoryRegion>,
_data_lifetime: PhantomData::<&'a [u8]>,
}
}
}
impl<'a> ScatterElement<'a> {
pub fn new(mr: &'a MemoryRegion, data: &'a mut [u8]) -> Self {
debug_assert!(data.len() <= u32::MAX as usize);
debug_assert!(mr.encloses_slice(data));
Self::new_unchecked(mr, data)
}
pub fn new_checked(
mr: &'a MemoryRegion,
data: &'a mut [u8],
) -> Result<Self, ScatterGatherElementError> {
if data.len() > u32::MAX as usize {
return Err(ScatterGatherElementError::SliceTooBig);
}
if !mr.encloses_slice(data) {
return Err(ScatterGatherElementError::SliceNotWithinBounds);
}
Ok(Self::new_unchecked(mr, data))
}
#[allow(clippy::cast_possible_truncation)]
pub fn new_unchecked(mr: &'a MemoryRegion, data: &'a mut [u8]) -> Self {
Self {
sge: ibv_sge {
addr: data.as_ptr() as u64,
length: data.len() as u32,
lkey: mr.lkey(),
},
_mr_lifetime: PhantomData::<&'a MemoryRegion>,
_data_lifetime: PhantomData::<&'a mut [u8]>,
}
}
}