use std::iter::Iterator;
use std::marker::PhantomData;
use std::mem::size_of;
#[derive(Debug, Clone)]
pub struct AlignByteSlice {
ptr: *mut (),
alignment: usize,
size: usize,
}
impl AlignByteSlice {
pub fn copy_from_slices(&mut self, slices: &[&[u8]]) {
self.ptr as *mut u8;
let mut current = 0;
for slice in slices {
unsafe {
assert!(current <= self.size, "");
let ptr = (self.ptr as *mut u8).offset(current as isize);
let raw_slice = ::std::slice::from_raw_parts_mut(ptr, slice.len());
raw_slice.copy_from_slice(slice);
current += slice.len();
let padding = current % self.alignment;
current += padding;
}
}
}
}
impl AlignByteSlice {
pub unsafe fn new(ptr: *mut (), alignment: usize, size: usize) -> Self {
AlignByteSlice {
ptr,
size,
alignment,
}
}
}
#[derive(Debug, Clone)]
pub struct Align<T> {
ptr: *mut (),
offset: usize,
size: usize,
_m: PhantomData<T>,
}
#[derive(Debug)]
pub struct AlignIter<'a, T: 'a> {
align: &'a mut Align<T>,
current: usize,
}
impl<T: Copy> Align<T> {
pub fn copy_from_slice(&mut self, slice: &[T]) {
for (i, val) in self.iter_mut().enumerate() {
*val = slice[i];
}
}
}
fn calc_padding(adr: usize, align: usize) -> usize {
(align - adr % align) % align
}
impl<T> Align<T> {
pub unsafe fn new(ptr: *mut (), alignment: usize, size: usize) -> Self {
let offset = size_of::<T>() + calc_padding(size_of::<T>(), alignment);
Align {
ptr,
offset,
size,
_m: PhantomData,
}
}
pub fn iter_mut(&mut self) -> AlignIter<T> {
AlignIter {
current: 0,
align: self,
}
}
}
impl<'a, T: Copy + 'a> Iterator for AlignIter<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.align.size {
return None;
}
unsafe {
let ptr = (self.align.ptr as *mut u8).offset(self.current as isize) as *mut T;
self.current += self.align.offset;
Some(&mut *ptr)
}
}
}