use std::convert::TryFrom;
use widestring::U16CString;
use winapi::{
shared::{
minwindef::UINT,
wtypes::{VT_BSTR, VT_INT, VT_UINT},
},
um::{
oaidl::VARIANT,
oleauto::{SysAllocStringLen, VariantInit},
},
};
use crate::VariantArgError;
#[derive(Debug)]
pub enum VariantArg {
Bstr(Vec<u16>),
Int(i32),
UInt(u32),
}
impl TryFrom<&str> for VariantArg {
type Error = VariantArgError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let bstr = U16CString::from_str(value)?;
Ok(VariantArg::Bstr(bstr.into_vec()))
}
}
impl TryFrom<&String> for VariantArg {
type Error = VariantArgError;
fn try_from(value: &String) -> Result<Self, Self::Error> {
VariantArg::try_from(value.as_str())
}
}
impl From<i32> for VariantArg {
fn from(val: i32) -> Self {
VariantArg::Int(val)
}
}
impl From<u32> for VariantArg {
fn from(val: u32) -> Self {
VariantArg::UInt(val)
}
}
impl Into<VARIANT> for VariantArg {
fn into(self) -> VARIANT {
let mut v = VARIANT::default();
unsafe {
VariantInit(&mut v);
}
match &self {
VariantArg::Bstr(bstr) => unsafe {
let bstr_ptr = SysAllocStringLen(bstr.as_ptr(), bstr.len() as UINT);
let n2 = v.n1.n2_mut();
n2.vt = VT_BSTR as u16;
let _val = n2.n3.bstrVal_mut();
*_val = bstr_ptr;
println!("assigning BSTR: {:?}", _val);
},
VariantArg::Int(value) => unsafe {
let n2 = v.n1.n2_mut();
n2.vt = VT_INT as u16;
let _val = n2.n3.intVal_mut();
*_val = *value;
},
VariantArg::UInt(value) => unsafe {
let n2 = v.n1.n2_mut();
n2.vt = VT_UINT as u16;
let _val = n2.n3.uintVal_mut();
*_val = *value;
},
}
v
}
}
#[test]
fn it_converts_str_to_bstr_arg() {
let src = "Test Value";
let _arg = VariantArg::try_from(src).unwrap();
if let VariantArg::Bstr(_arg) = _arg {
let bstr = U16CString::from_str(src).unwrap().into_vec();
if !bstr.eq(&_arg) {
panic!("value in argument does not generate a valid wide char array");
}
} else {
panic!(format!("expected argument to be BSTR, got: {:?}", _arg));
}
}
#[test]
fn it_converts_string_to_bstr_arg() {
let src = String::from("Test Value");
let _arg = VariantArg::try_from(&src).unwrap();
if let VariantArg::Bstr(_arg) = _arg {
let bstr = U16CString::from_str(src.as_str()).unwrap().into_vec();
if !bstr.eq(&_arg) {
panic!("value in argument does not generate a valid wide char array");
}
} else {
panic!(format!("expected argument to be BSTR, got: {:?}", _arg));
}
}
#[test]
fn it_converts_i32_to_int_arg() {
let src: i32 = 1234;
let _arg = VariantArg::from(src);
if let VariantArg::Int(_arg) = _arg {
if _arg != src {
panic!(format!("expected {:}, got {:}", src, _arg));
}
} else {
panic!(format!("expected argument to be Int, got {:?}", _arg));
}
}
#[test]
fn it_converts_u32_to_int_arg() {
let src: u32 = 1234;
let _arg = VariantArg::from(src);
if let VariantArg::UInt(_arg) = _arg {
if _arg != src {
panic!(format!("expected {:}, got {:}", src, _arg));
}
} else {
panic!(format!("expected argument to be Uint, got {:?}", _arg));
}
}