diff --git a/intercom-attributes/tests/data/run/generic-coclass.rs b/intercom-attributes/tests/data/run/generic-coclass.rs new file mode 100644 index 0000000..752e909 --- /dev/null +++ b/intercom-attributes/tests/data/run/generic-coclass.rs @@ -0,0 +1,181 @@ +extern crate intercom; +use intercom::attributes::HasInterface; +use intercom::prelude::*; +use std::cell::RefCell; + +#[com_interface] +trait IAnimal +{ + fn get_name(&self) -> ComResult; + fn describe(&self) -> ComResult; +} + +// Crab + +#[com_interface] +trait ICrab +{ + fn pick_up(&self, item: &str) -> ComResult<()>; +} + +#[com_class(IAnimal, ICrab)] +#[derive(Default)] +struct Crab +{ + name: &'static str, + item: RefCell>, +} + +impl Crab +{ + fn new(name: &'static str) -> Crab + { + Crab { + name, + item: RefCell::new(None), + } + } +} + +impl ICrab for Crab +{ + fn pick_up(&self, item: &str) -> ComResult<()> + { + self.item.replace(Some(item.to_string())); + Ok(()) + } +} + +impl IAnimal for Crab +{ + fn get_name(&self) -> ComResult + { + Ok(self.name.to_string()) + } + + fn describe(&self) -> ComResult + { + match *self.item.borrow() { + Some(ref item) => Ok(format!("A crab called {} carrying {}", self.name, item)), + None => Ok(format!("A crab called {} who is empty pincered", self.name)), + } + } +} + +// Dog + +#[com_interface] +trait IDog +{ +} + +#[com_class(IAnimal, IDog)] +#[derive(Default)] +struct Dog +{ + name: &'static str, +} + +impl IDog for Dog {} +impl IAnimal for Dog +{ + fn get_name(&self) -> ComResult + { + Ok(self.name.to_string()) + } + + fn describe(&self) -> ComResult + { + Ok(format!("A dog called {}", self.name)) + } +} + +// Generic collection + +#[com_interface] +trait ICollection +{ + fn get_count(&self) -> usize; + fn get_item(&self, idx: usize) -> ComResult>; +} + +#[com_class(ICollection)] +struct Collection + Default> +{ + items: Vec>, +} + +impl + Default> ICollection for Collection +{ + fn get_count(&self) -> usize + { + self.items.len() + } + + fn get_item(&self, idx: usize) -> ComResult> + { + Ok(self + .items + .get(idx) + .map(|item| item.into()) + .unwrap_or_else(|| ComBox::new(T::default()).into())) + } +} + +// A factory that returns generic collections. + +#[com_class(Self)] +struct Factory; + +#[com_interface] +impl Factory +{ + fn get_crabs(&self) -> ComResult> + { + let collection = ComBox::new(Collection { + items: vec![ + ComBox::new(Crab::new("Ferris")), + ComBox::new(Crab::new("Pincers")), + ComBox::new(Crab::new("Shelly")), + ], + }); + + Ok(collection.into()) + } + + fn get_dogs(&self) -> ComResult> + { + let collection = ComBox::new(Collection { + items: vec![ + ComBox::new(Dog { name: "Spot" }), + ComBox::new(Dog { name: "Stripe" }), + ComBox::new(Dog { name: "Checkers" }), + ], + }); + + Ok(collection.into()) + } +} + +fn main() +{ + // Instantiate Factory as a COM interface. + let factory = ComBox::new(Factory); + let factory: ComRc = factory.into(); + + // Make crabs pick up stuff. + let crab_collection = factory.get_crabs().expect("Failed to get crabs"); + let items = ["borrowck", "fish", "gear"]; + for i in 0..crab_collection.get_count() { + let animal = crab_collection.get_item(i).expect("Failed to get item"); + let crab: ComRc = intercom::ComItf::query_interface(&animal) + .expect("Crab collection had a non-crab item"); + crab.pick_up(items[i]); + } + + // Describe each crab. + for i in 0..crab_collection.get_count() { + let animal = crab_collection.get_item(i).expect("Failed to get item"); + println!("{}", animal.describe().expect("Failed to describe")); + } +} diff --git a/intercom-attributes/tests/data/run/generic-coclass.rs.stdout b/intercom-attributes/tests/data/run/generic-coclass.rs.stdout new file mode 100644 index 0000000..77eaa68 --- /dev/null +++ b/intercom-attributes/tests/data/run/generic-coclass.rs.stdout @@ -0,0 +1,3 @@ +A crab called Ferris carrying borrowck +A crab called Pincers carrying fish +A crab called Shelly carrying gear