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}