use super::{SafeDispatch, SafeVariant};
use crate::errors::{SageError, SageResult};
use windows::Win32::System::Com::IDispatch;
pub struct ComCollection {
dispatch: IDispatch,
}
impl ComCollection {
pub fn new(dispatch: IDispatch) -> Self {
Self { dispatch }
}
pub fn from_variant(variant: SafeVariant) -> SageResult<Self> {
if variant.is_object() {
let dispatch = variant.to_dispatch()?;
Ok(Self::new(dispatch))
} else {
Err(SageError::ConversionError {
from_type: "SafeVariant".to_string(),
to_type: "ComCollection".to_string(),
value: "Le variant ne contient pas un objet COM".to_string(),
})
}
}
fn dispatch(&self) -> SafeDispatch<'_> {
SafeDispatch::new(&self.dispatch)
}
pub fn count(&self) -> SageResult<i32> {
self.dispatch().get_property_by_name("Count")?.to_i32()
}
pub fn item(&self, index: i32) -> SageResult<IDispatch> {
let index_variant = SafeVariant::I4(index);
let result = self
.dispatch()
.call_method_by_name("Item", &[index_variant])?;
result.to_dispatch()
}
pub fn is_empty(&self) -> SageResult<bool> {
Ok(self.count()? == 0)
}
pub fn iter(&self) -> ComCollectionIterator<'_> {
ComCollectionIterator {
collection: self,
current_index: 1,
count: self.count().unwrap_or(0),
}
}
pub fn to_vec(&self) -> SageResult<Vec<IDispatch>> {
let count = self.count()?;
let mut items = Vec::with_capacity(count as usize);
for i in 1..=count {
items.push(self.item(i)?);
}
Ok(items)
}
}
pub struct ComCollectionIterator<'a> {
collection: &'a ComCollection,
current_index: i32,
count: i32,
}
impl<'a> Iterator for ComCollectionIterator<'a> {
type Item = SageResult<IDispatch>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_index > self.count {
return None;
}
let result = self.collection.item(self.current_index);
self.current_index += 1;
Some(result)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = (self.count - self.current_index + 1) as usize;
(remaining, Some(remaining))
}
}
impl<'a> ExactSizeIterator for ComCollectionIterator<'a> {}
pub struct TypedComCollection<T>
where
T: FromDispatchNew,
{
inner: ComCollection,
_marker: std::marker::PhantomData<T>,
}
impl<T> TypedComCollection<T>
where
T: FromDispatchNew,
{
pub fn new(collection: ComCollection) -> Self {
Self {
inner: collection,
_marker: std::marker::PhantomData,
}
}
pub fn from_variant(variant: SafeVariant) -> SageResult<Self> {
let collection = ComCollection::from_variant(variant)?;
Ok(Self::new(collection))
}
pub fn count(&self) -> SageResult<i32> {
self.inner.count()
}
pub fn is_empty(&self) -> SageResult<bool> {
self.inner.is_empty()
}
pub fn item(&self, index: i32) -> SageResult<T> {
let dispatch = self.inner.item(index)?;
T::from_dispatch_new(dispatch)
}
pub fn iter(&self) -> TypedComCollectionIterator<'_, T> {
TypedComCollectionIterator {
collection: self,
current_index: 1,
count: self.inner.count().unwrap_or(0),
}
}
pub fn to_vec(&self) -> SageResult<Vec<T>> {
let count = self.inner.count()?;
let mut items = Vec::with_capacity(count as usize);
for i in 1..=count {
items.push(self.item(i)?);
}
Ok(items)
}
}
pub struct TypedComCollectionIterator<'a, T>
where
T: FromDispatchNew,
{
collection: &'a TypedComCollection<T>,
current_index: i32,
count: i32,
}
impl<'a, T> Iterator for TypedComCollectionIterator<'a, T>
where
T: FromDispatchNew,
{
type Item = SageResult<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_index > self.count {
return None;
}
let result = self.collection.item(self.current_index);
self.current_index += 1;
Some(result)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = (self.count - self.current_index + 1) as usize;
(remaining, Some(remaining))
}
}
impl<'a, T> ExactSizeIterator for TypedComCollectionIterator<'a, T> where T: FromDispatchNew {}
pub trait FromDispatchNew: Sized {
fn from_dispatch_new(dispatch: IDispatch) -> SageResult<Self>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_collection_documentation() {
}
}