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}