use std::marker::PhantomData;
use std::os::raw::c_int;
use std::{mem, ptr};
use super::*;
use crate::ffi;
pub struct Buffer {
pub(crate) buf: *mut ffi::iio_buffer,
pub(crate) cap: usize,
#[allow(dead_code)]
pub(crate) ctx: Context,
}
impl Buffer {
pub fn capacity(&self) -> usize {
self.cap
}
pub fn poll_fd(&mut self) -> Result<c_int> {
let ret = unsafe { ffi::iio_buffer_get_poll_fd(self.buf) };
sys_result(i32::from(ret), ret)
}
pub fn set_blocking_mode(&mut self, blocking: bool) -> Result<()> {
let ret = unsafe { ffi::iio_buffer_set_blocking_mode(self.buf, blocking) };
sys_result(ret, ())
}
pub fn refill(&mut self) -> Result<usize> {
let ret = unsafe { ffi::iio_buffer_refill(self.buf) };
sys_result(ret as i32, ret as usize)
}
pub fn push(&mut self) -> Result<usize> {
let ret = unsafe { ffi::iio_buffer_push(self.buf) };
sys_result(ret as i32, ret as usize)
}
pub fn push_partial(&mut self, n: usize) -> Result<usize> {
let ret = unsafe { ffi::iio_buffer_push_partial(self.buf, n) };
sys_result(ret as i32, ret as usize)
}
pub fn cancel(&mut self) {
unsafe {
ffi::iio_buffer_cancel(self.buf);
}
}
pub fn channel_iter<T>(&self, chan: &Channel) -> IntoIter<T> {
unsafe {
let begin = ffi::iio_buffer_first(self.buf, chan.chan) as *mut T;
let end = ffi::iio_buffer_end(self.buf) as *const T;
let ptr = begin;
let step: isize = ffi::iio_buffer_step(self.buf) / mem::size_of::<T>() as isize;
IntoIter {
phantom: PhantomData,
ptr,
end,
step,
}
}
}
}
impl Drop for Buffer {
fn drop(&mut self) {
unsafe { ffi::iio_buffer_destroy(self.buf) }
}
}
pub struct IntoIter<T> {
phantom: PhantomData<T>,
ptr: *const T,
end: *const T,
step: isize,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
unsafe {
if self.ptr as *const _ >= self.end {
None
}
else {
let prev = self.ptr;
self.ptr = self.ptr.offset(self.step);
Some(ptr::read(prev))
}
}
}
}