1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Defines the iterable list of processing blocks.

use crate::{
    error::{ErrorChecker, Result as RsResult},
    processing_block::{marker as processing_block_marker, ProcessingBlock},
};
use std::{iter::FusedIterator, mem::MaybeUninit, os::raw::c_int, ptr::NonNull};

/// The iterable list of [ProcessingBlock](ProcessingBlock)s.
#[derive(Debug)]
pub struct ProcessingBlockList {
    ptr: NonNull<realsense_sys::rs2_processing_block_list>,
}

impl ProcessingBlockList {
    /// Retrieves the [ProcessingBlock](ProcessingBlock) instance at index.
    pub fn get(&mut self, index: usize) -> RsResult<ProcessingBlock<processing_block_marker::Any>> {
        let block = unsafe {
            let mut checker = ErrorChecker::new();
            let ptr = realsense_sys::rs2_get_processing_block(
                self.ptr.as_ptr(),
                index as c_int,
                checker.inner_mut_ptr(),
            );
            checker.check()?;
            ProcessingBlock::from_ptr(NonNull::new(ptr).unwrap())
        };
        Ok(block)
    }

    /// Returns the length of list.
    pub fn len(&mut self) -> RsResult<usize> {
        unsafe {
            let mut checker = ErrorChecker::new();
            let val = realsense_sys::rs2_get_recommended_processing_blocks_count(
                self.ptr.as_ptr(),
                checker.inner_mut_ptr(),
            );
            checker.check()?;
            Ok(val as usize)
        }
    }

    /// Converts to iterator type.
    pub fn try_into_iter(mut self) -> RsResult<ProcessingBlockListIntoIter> {
        let len = self.len()?;
        let ptr = unsafe { self.take() };
        let iter = ProcessingBlockListIntoIter { len, index: 0, ptr };
        Ok(iter)
    }

    pub(crate) unsafe fn take(mut self) -> NonNull<realsense_sys::rs2_processing_block_list> {
        let ptr = std::mem::replace(&mut self.ptr, { MaybeUninit::uninit().assume_init() });
        std::mem::forget(self);
        ptr
    }

    pub(crate) unsafe fn from_ptr(ptr: NonNull<realsense_sys::rs2_processing_block_list>) -> Self {
        Self { ptr }
    }
}

impl IntoIterator for ProcessingBlockList {
    type Item = RsResult<ProcessingBlock<processing_block_marker::Any>>;
    type IntoIter = ProcessingBlockListIntoIter;

    /// The method calls [ProcessingBlockList::try_into_iter](ProcessingBlockList::try_into_iter).
    ///
    /// # Panics
    /// It panics if [ProcessingBlockList::try_into_iter](ProcessingBlockList::try_into_iter) returns [Err](Result::Err).
    fn into_iter(self) -> Self::IntoIter {
        self.try_into_iter().unwrap()
    }
}

impl Drop for ProcessingBlockList {
    fn drop(&mut self) {
        unsafe {
            realsense_sys::rs2_delete_recommended_processing_blocks(self.ptr.as_ptr());
        }
    }
}

/// The iterator type returned by [ProcessingBlockList::try_into_iter](ProcessingBlockList::try_into_iter).
pub struct ProcessingBlockListIntoIter {
    len: usize,
    index: usize,
    ptr: NonNull<realsense_sys::rs2_processing_block_list>,
}

impl Iterator for ProcessingBlockListIntoIter {
    type Item = RsResult<ProcessingBlock<processing_block_marker::Any>>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.len {
            let block = unsafe {
                let mut checker = ErrorChecker::new();
                let ptr = realsense_sys::rs2_get_processing_block(
                    self.ptr.as_ptr(),
                    self.index as c_int,
                    checker.inner_mut_ptr(),
                );
                match checker.check() {
                    Ok(()) => ProcessingBlock::from_ptr(NonNull::new(ptr).unwrap()),
                    Err(err) => return Some(Err(err)),
                }
            };
            self.index += 1;
            Some(Ok(block))
        } else {
            None
        }
    }
}

impl FusedIterator for ProcessingBlockListIntoIter {}

impl Drop for ProcessingBlockListIntoIter {
    fn drop(&mut self) {
        unsafe {
            realsense_sys::rs2_delete_recommended_processing_blocks(self.ptr.as_ptr());
        }
    }
}