outlook_mapi/
row.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT license.
3
4//! Define [`Row`].
5
6use crate::{PropValue, sys};
7use core::{mem, slice};
8use std::ptr;
9
10/// Container for the members of a [`sys::SRow`] structure. The [`sys::SPropValue`] pointer should
11/// be freed in the destructor with a call to [`sys::MAPIFreeBuffer`].
12///
13/// Typically, the memory for the [`sys::SRow`] itself is still owned by an [`sys::SRowSet`]
14/// allocation, but the [`sys::SRow::lpProps`] member is a separate allocation. [`Row`] copies the
15/// [`sys::SRow::cValues`] member and takes ownership of the [`sys::SRow::lpProps`] pointer away
16/// from the [`sys::SRow`], leaving both [`sys::SRow`] members empty in the source structure.
17pub struct Row {
18    count: usize,
19    props: *mut sys::SPropValue,
20}
21
22impl Row {
23    /// Take ownership of the [`sys::SRow`] members.
24    pub fn new(row: &mut sys::SRow) -> Self {
25        Self {
26            count: mem::replace(&mut row.cValues, 0) as usize,
27            props: mem::replace(&mut row.lpProps, ptr::null_mut()),
28        }
29    }
30
31    /// Test for a count of 0 properties or a null [`sys::SPropValue`] pointer.
32    pub fn is_empty(&self) -> bool {
33        self.count == 0 || self.props.is_null()
34    }
35
36    /// Get the number of [`sys::SPropValue`] column values in the [`Row`].
37    pub fn len(&self) -> usize {
38        if self.props.is_null() { 0 } else { self.count }
39    }
40
41    /// Iterate over the [`sys::SPropValue`] column values in the [`Row`].
42    pub fn iter(&self) -> impl Iterator<Item = PropValue> {
43        if self.props.is_null() {
44            vec![]
45        } else {
46            unsafe {
47                let data: &[sys::SPropValue] = slice::from_raw_parts(self.props, self.count);
48                data.iter().map(PropValue::from).collect()
49            }
50        }
51        .into_iter()
52    }
53}
54
55impl Drop for Row {
56    /// Free the [`sys::SPropValue`] pointer with [`sys::MAPIFreeBuffer`].
57    fn drop(&mut self) {
58        if !self.props.is_null() {
59            unsafe {
60                sys::MAPIFreeBuffer(self.props as *mut _);
61            }
62        }
63    }
64}