use rs_teststand_sys::{Dispatch, Value};
use crate::Error;
use crate::dispids::sequence;
use crate::property::PropertyObject;
#[derive(Debug)]
pub struct Sequence {
dispatch: Box<dyn Dispatch>,
}
impl Sequence {
pub(crate) fn new(dispatch: Box<dyn Dispatch>) -> Self {
Self { dispatch }
}
pub fn name(&self) -> Result<String, Error> {
Ok(self.dispatch.get(sequence::NAME)?.into_string()?)
}
pub fn set_name(&self, name: &str) -> Result<(), Error> {
self.dispatch
.put(sequence::NAME, Value::Str(name.to_owned()))?;
Ok(())
}
pub(crate) fn duplicate_dispatch(&self) -> Option<Box<dyn Dispatch>> {
self.dispatch.duplicate()
}
pub fn get_num_steps(&self, group: crate::StepGroup) -> Result<i32, Error> {
Ok(self
.dispatch
.call(sequence::GET_NUM_STEPS, &[Value::I32(group.bits())])?
.as_i32()?)
}
pub fn get_step(&self, index: i32, group: crate::StepGroup) -> Result<crate::Step, Error> {
Ok(crate::Step::new(
self.dispatch
.call(
sequence::GET_STEP,
&[Value::I32(index), Value::I32(group.bits())],
)?
.into_object()?,
))
}
pub fn insert_step(
&self,
step: &crate::Step,
index: i32,
group: crate::StepGroup,
) -> Result<(), Error> {
let handle = step.duplicate_dispatch().ok_or(Error::UnexpectedType {
expected: "a live step object",
actual: "a test fake with no COM identity",
})?;
self.dispatch.call(
sequence::INSERT_STEP,
&[
Value::Object(handle),
Value::I32(index),
Value::I32(group.bits()),
],
)?;
Ok(())
}
pub fn insert_step_from_template(
&self,
template: &PropertyObject,
index: i32,
group: crate::StepGroup,
) -> Result<crate::Step, Error> {
let copy = template.clone_property("", crate::PropertyOptions::NONE.bits())?;
let handle = copy.duplicate_dispatch().ok_or(Error::UnexpectedType {
expected: "a live template object",
actual: "a test fake with no COM identity",
})?;
self.dispatch.call(
sequence::INSERT_STEP,
&[
Value::Object(handle),
Value::I32(index),
Value::I32(group.bits()),
],
)?;
self.get_step(index, group)
}
pub fn as_property_object(&self) -> Result<PropertyObject, Error> {
Ok(PropertyObject::new(
self.dispatch
.call(sequence::AS_PROPERTY_OBJECT, &[])?
.into_object()?,
))
}
pub fn create_new_unique_step_ids(&self) -> Result<(), Error> {
self.dispatch
.call(sequence::CREATE_NEW_UNIQUE_STEP_IDS, &[])?;
Ok(())
}
pub fn locals(&self) -> Result<PropertyObject, Error> {
Ok(PropertyObject::new(
self.dispatch.get(sequence::LOCALS)?.into_object()?,
))
}
pub fn parameters(&self) -> Result<PropertyObject, Error> {
Ok(PropertyObject::new(
self.dispatch.get(sequence::PARAMETERS)?.into_object()?,
))
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use rs_teststand_sys::{ComError, Dispatch, Value};
use super::Sequence;
use crate::Error;
use crate::dispids::sequence;
#[derive(Debug)]
struct Fake {
properties: HashMap<i32, Value>,
}
impl Dispatch for Fake {
fn get(&self, dispid: i32) -> Result<Value, ComError> {
match self.properties.get(&dispid) {
Some(Value::Str(text)) => Ok(Value::Str(text.clone())),
_ => Err(ComError::hresult(-17000, "fake: unscripted")),
}
}
fn put(&self, _dispid: i32, _value: Value) -> Result<(), ComError> {
Ok(())
}
fn call(&self, _dispid: i32, _args: &[Value]) -> Result<Value, ComError> {
Err(ComError::hresult(-17000, "fake: unscripted"))
}
}
#[test]
fn reads_its_name() -> Result<(), Error> {
let sequence = Sequence::new(Box::new(Fake {
properties: HashMap::from([(sequence::NAME, Value::Str("MainSequence".to_owned()))]),
}));
assert_eq!(sequence.name()?, "MainSequence");
Ok(())
}
#[test]
fn locals_and_parameters_are_distinct_dispids() {
assert_ne!(sequence::LOCALS, sequence::PARAMETERS);
assert_eq!(sequence::LOCALS, 0x33);
assert_eq!(sequence::PARAMETERS, 0x32);
}
}