use crate::query_sink::{IWbemObjectSink, QuerySink};
use crate::result_enumerator::IWbemClassWrapper;
use crate::{connection::WMIConnection, utils::check_hres, WMIResult};
use crate::{
query::{build_query, FilterValue},
BStr,
};
use com::production::ClassAllocation;
use com::AbiTransferable;
use futures::stream::{Stream, StreamExt, TryStreamExt};
use serde::de;
use std::{collections::HashMap, ptr};
use winapi::um::wbemcli::WBEM_FLAG_BIDIRECTIONAL;
impl WMIConnection {
pub fn exec_query_async_native_wrapper(
&self,
query: impl AsRef<str>,
) -> WMIResult<impl Stream<Item = WMIResult<IWbemClassWrapper>>> {
let query_language = BStr::from_str("WQL")?;
let query = BStr::from_str(query.as_ref())?;
let (tx, rx) = async_channel::unbounded();
let p_sink: ClassAllocation<QuerySink> = QuerySink::allocate(Some(tx));
let p_sink_handel = p_sink.query_interface::<IWbemObjectSink>().unwrap();
unsafe {
check_hres((*self.svc()).ExecQueryAsync(
query_language.as_bstr(),
query.as_bstr(),
WBEM_FLAG_BIDIRECTIONAL as i32,
ptr::null_mut(),
p_sink_handel.get_abi().as_ptr() as *mut _,
))?;
}
Ok(rx)
}
pub async fn async_raw_query<T>(&self, query: impl AsRef<str>) -> WMIResult<Vec<T>>
where
T: de::DeserializeOwned,
{
self.exec_query_async_native_wrapper(query)?
.map(|item| match item {
Ok(wbem_class_obj) => wbem_class_obj.into_desr(),
Err(e) => Err(e),
})
.try_collect::<Vec<_>>()
.await
}
pub async fn async_query<T>(&self) -> WMIResult<Vec<T>>
where
T: de::DeserializeOwned,
{
let query_text = build_query::<T>(None)?;
self.async_raw_query(&query_text).await
}
pub async fn async_filtered_query<T>(
&self,
filters: &HashMap<String, FilterValue>,
) -> WMIResult<Vec<T>>
where
T: de::DeserializeOwned,
{
let query_text = build_query::<T>(Some(&filters))?;
self.async_raw_query(&query_text).await
}
}
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
#[cfg(test)]
mod tests {
use crate::tests::fixtures::*;
use crate::Variant;
use futures::stream::StreamExt;
use std::collections::HashMap;
#[async_std::test]
async fn async_it_works_async() {
let wmi_con = wmi_con();
let result = wmi_con
.exec_query_async_native_wrapper("SELECT OSArchitecture FROM Win32_OperatingSystem")
.unwrap()
.collect::<Vec<_>>()
.await;
assert_eq!(result.len(), 1);
}
#[async_std::test]
async fn async_it_handles_invalid_query() {
let wmi_con = wmi_con();
let result = wmi_con
.exec_query_async_native_wrapper("invalid query")
.unwrap()
.collect::<Vec<_>>()
.await;
assert_eq!(result.len(), 0);
}
#[async_std::test]
async fn async_it_provides_raw_query_result() {
let wmi_con = wmi_con();
let results: Vec<HashMap<String, Variant>> = wmi_con
.async_raw_query("SELECT * FROM Win32_GroupUser")
.await
.unwrap();
for res in results {
match res.get("GroupComponent") {
Some(Variant::String(s)) => assert!(s != ""),
_ => assert!(false),
}
match res.get("PartComponent") {
Some(Variant::String(s)) => assert!(s != ""),
_ => assert!(false),
}
}
}
}