Skip to content

Commit

Permalink
Updated buffer iterators:
Browse files Browse the repository at this point in the history
- Implemented mutable Buffer iterator (untested)
- Buffer iterator now returns a reference to the item.
- Added a lifetime to the buffer iterator
  • Loading branch information
fpagliughi committed Sep 23, 2023
1 parent b2cf10c commit 0995d4e
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 24 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,20 @@ To keep up with the latest announcements for this project, follow:

**Twitter:** [@fmpagliughi](https://twitter.com/fmpagliughi)

### Unreleased Features in this Branch
### Unreleased Features in this Branch (Upcoming v0.6)

- Targeting Rust Edition 2021 with MSRV v1.65
- Converted to explicit re-exports to avoid ambigious warnings.
- Added a mutable iterator for channel data in a buffer (to fill the buffer)
- Added lifetime to buffer iterator so as not to outlive the buffer.
- [Breaking]: Buffer iterator now returns a reference to the item in the buffer, to be consistent with mutable iterator and slice iterators.
- [PR #28](https://github.com/fpagliughi/rust-industrial-io/pull/28)- Move set_num_kernel_buffers() to Device
- [PR #22](https://github.com/fpagliughi/rust-industrial-io/pull/22)- Disable chrono default features to mitigate segfault potential in time crate
- Updated to `clap` v3.2
- Support and bindings for libiio v0.25
- Cargo build features for selecting bindings to older libiio versions (v0.24, v0.23, etc)
-
- Added initial CI support to test building and format. (Still can't run unit tests in CI due to iio kernel module requirements).

### New in Version 0.5.2

- [PR #26](https://github.com/fpagliughi/rust-industrial-io/pull/26) - Added 'utilities' feature to be able to turn off build of binary applications (i.e. only build the library).
Expand Down
1 change: 1 addition & 0 deletions examples/riio_bufavg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ fn run() -> Result<()> {
let ts: u64 = if let Some(ref chan) = ts_chan {
buf.channel_iter::<u64>(chan)
.nth(n_sample - 1)
.map(|&x| x)
.unwrap_or_default()
}
else {
Expand Down
2 changes: 1 addition & 1 deletion examples/riio_free_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ fn main() {
}

for chan in dev.channels() {
let data: Vec<u16> = buf.channel_iter::<u16>(&chan).collect();
let data: Vec<u16> = buf.channel_iter::<u16>(&chan).map(|&x| x).collect();
println!("{}: {:?}", chan.id().unwrap_or_default(), data);
}
}
2 changes: 1 addition & 1 deletion examples/riio_tsbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn run() -> Result<()> {
// nanoseconds since the Unix Epoch. We convert to a Rust SystemTime,
// then a chrono DataTime for pretty printing.
buf.channel_iter::<u16>(&sample_chan)
.zip(ts_data.map(|ts| {
.zip(ts_data.map(|&ts| {
DateTime::<Utc>::from(SystemTime::UNIX_EPOCH + Duration::from_nanos(ts))
.format("%T%.6f")
}))
Expand Down
100 changes: 80 additions & 20 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ use std::{
marker::PhantomData,
mem,
os::raw::{c_int, c_longlong},
ptr,
};

use super::*;
Expand Down Expand Up @@ -328,20 +327,13 @@ impl Buffer {
}

/// Gets an iterator for the data from a channel.
pub fn channel_iter<T>(&self, chan: &Channel) -> IntoIter<T> {
unsafe {
let begin = ffi::iio_buffer_first(self.buf, chan.chan).cast();
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;
pub fn channel_iter<T>(&self, chan: &Channel) -> Iter<'_, T> {
Iter::new(self, chan)
}

IntoIter {
phantom: PhantomData,
ptr,
end,
step,
}
}
/// Gets a mutable iterator for the data to a channel.
pub fn channel_iter_mut<T>(&mut self, chan: &Channel) -> IterMut<'_, T> {
IterMut::new(self, chan)
}
}

Expand All @@ -354,8 +346,8 @@ impl Drop for Buffer {

/// An iterator that moves channel data out of a buffer.
#[derive(Debug)]
pub struct IntoIter<T> {
phantom: PhantomData<T>,
pub struct Iter<'a, T: 'a> {
_phantom: PhantomData<&'a T>,
// Pointer to the current sample for a channel
ptr: *const T,
// Pointer to the end of the buffer
Expand All @@ -364,18 +356,86 @@ pub struct IntoIter<T> {
step: isize,
}

impl<T> Iterator for IntoIter<T> {
type Item = T;
impl<'a, T> Iter<'a, T> {
/// Create an iterator to move channel data out of a buffer.
pub fn new(buf: &Buffer, chan: &Channel) -> Self {
unsafe {
let begin = ffi::iio_buffer_first(buf.buf, chan.chan).cast();
let end = ffi::iio_buffer_end(buf.buf).cast();
let ptr = begin;
let step: isize = ffi::iio_buffer_step(buf.buf) / mem::size_of::<T>() as isize;

fn next(&mut self) -> Option<T> {
Self {
_phantom: PhantomData,
ptr,
end,
step,
}
}
}
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
type Item = &'a T;

fn next(&mut self) -> Option<Self::Item> {
unsafe {
if self.ptr.cast() >= self.end {
None
}
else {
let prev = self.ptr;
self.ptr = self.ptr.offset(self.step);
Some(ptr::read(prev))
Some(&*prev)
}
}
}
}

/// A mutable iterator to move channel data into a buffer.
#[derive(Debug)]
pub struct IterMut<'a, T: 'a> {
// Reference to the buffer lifetime
_phantom: PhantomData<&'a mut T>,
// Pointer to the current sample for a channel
ptr: *mut T,
// Pointer to the end of the buffer
end: *const T,
// The offset to the next sample for the channel
step: isize,
}

impl<'a, T: 'a> IterMut<'a, T> {
/// Create a mutable iterator to move channel data into a buffer.
pub fn new(buf: &'a mut Buffer, chan: &Channel) -> Self {
unsafe {
let begin = ffi::iio_buffer_first(buf.buf, chan.chan).cast();
let end = ffi::iio_buffer_end(buf.buf).cast();
let ptr = begin;
let step: isize = ffi::iio_buffer_step(buf.buf) / mem::size_of::<T>() as isize;

Self {
_phantom: PhantomData,
ptr,
end,
step,
}
}
}
}

impl<'a, T: 'a> Iterator for IterMut<'a, T> {
type Item = &'a mut T;

fn next(&mut self) -> Option<Self::Item> {
if self.ptr as *const T >= self.end {
None
}
else {
unsafe {
let prev = self.ptr;
self.ptr = self.ptr.offset(self.step);
Some(&mut *prev)
}
}
}
Expand Down

0 comments on commit 0995d4e

Please sign in to comment.