outlook_mapi/
row_set.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT license.
3
4//! Define [`RowSet`].
5
6use crate::{Row, sys};
7use core::{ptr, slice};
8
9/// Container for a [`sys::SRowSet`] structure, such as the rows returned from
10/// [`sys::IMAPITable::QueryRows`].
11///
12/// The `*mut sys::SRowSet` should be freed with a call to [`sys::FreeProws`] in the destructor,
13/// but [`sys::SRowSet`] allows embedded [`sys::SPropValue`] pointers to be peeled off and freed
14/// separately, as long as the pointer in the [`sys::SRowSet`] is replaced with `null`. The
15/// [`sys::FreeProws`] function will free any non-`null` property pointers in the [`sys::SRowSet`],
16/// but silently skip the ones that are `null`.
17pub struct RowSet {
18    rows: *mut sys::SRowSet,
19}
20
21impl RowSet {
22    /// Get an out-param pointer for the [`sys::SRowSet`] pointer.
23    pub fn as_mut_ptr(&mut self) -> *mut *mut sys::SRowSet {
24        &mut self.rows
25    }
26
27    /// Test for a `null` [`sys::SRowSet`] pointer or a pointer to 0 rows.
28    pub fn is_empty(&self) -> bool {
29        unsafe {
30            self.rows
31                .as_ref()
32                .map(|rows| rows.cRows == 0)
33                .unwrap_or(true)
34        }
35    }
36
37    /// Get the count of rows contained in the [`sys::SRowSet`].
38    pub fn len(&self) -> usize {
39        unsafe {
40            self.rows
41                .as_ref()
42                .map(|rows| rows.cRows as usize)
43                .unwrap_or_default()
44        }
45    }
46}
47
48impl Default for RowSet {
49    /// The initial state for [`RowSet`] should have a `null` `*mut sys::SRowSet` pointer. An
50    /// allocation should be added to it later using the [`RowSet::as_mut_ptr`] method to fill in
51    /// an out-param from one of the [`sys`] functions or interface methods which retrieve a
52    /// [`sys::SRowSet`] structure.
53    fn default() -> Self {
54        Self {
55            rows: ptr::null_mut(),
56        }
57    }
58}
59
60impl IntoIterator for RowSet {
61    type Item = Row;
62    type IntoIter = <Vec<Self::Item> as IntoIterator>::IntoIter;
63
64    /// Transfer ownership of the embedded [`sys::SPropValue`] pointers to an [`Iterator`] of
65    /// [`Row`].
66    fn into_iter(self) -> Self::IntoIter {
67        unsafe {
68            if let Some(rows) = self.rows.as_mut() {
69                let count = rows.cRows as usize;
70                let data: &mut [sys::SRow] =
71                    slice::from_raw_parts_mut(rows.aRow.as_mut_ptr(), count);
72                data.iter_mut().map(Row::new).collect()
73            } else {
74                vec![]
75            }
76        }
77        .into_iter()
78    }
79}
80
81impl Drop for RowSet {
82    /// Call [`sys::FreeProws`] to free the `*mut sys::SRowSet`. This will also free any
83    /// [`sys::SPropValue`] pointers that have not been transfered to an instance of [`Row`].
84    fn drop(&mut self) {
85        if !self.rows.is_null() {
86            unsafe {
87                sys::FreeProws(self.rows);
88            }
89        }
90    }
91}