summaryrefslogtreecommitdiffstats
path: root/crates/core/tedge_lib/src/iter/result.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/core/tedge_lib/src/iter/result.rs')
-rw-r--r--crates/core/tedge_lib/src/iter/result.rs120
1 files changed, 120 insertions, 0 deletions
diff --git a/crates/core/tedge_lib/src/iter/result.rs b/crates/core/tedge_lib/src/iter/result.rs
new file mode 100644
index 00000000..6a1e7335
--- /dev/null
+++ b/crates/core/tedge_lib/src/iter/result.rs
@@ -0,0 +1,120 @@
+/// A Result helper type that can be collected
+///
+/// ```no_run
+/// # async {
+/// # #[derive(Clone, Debug, bevy_reflect::TypeUuid)]
+/// # #[uuid = "e9457c98-e956-4403-89ff-33635bf18ee3"]
+/// # struct M;
+/// # impl tedge_api::Message for M {}
+/// # tedge_api::make_receiver_bundle!(struct MessageReceiver(M));
+/// #
+/// # struct PD;
+/// # impl tedge_api::PluginDirectory for PD {
+/// # fn get_address_for<RB: tedge_api::address::ReceiverBundle>(
+/// # &self,
+/// # name: &str,
+/// # ) -> Result<tedge_api::Address<RB>, tedge_api::error::DirectoryError> {
+/// # unimplemented!()
+/// # }
+/// # fn get_address_for_core(&self) -> tedge_api::Address<tedge_api::message::CoreMessages> {
+/// # unimplemented!()
+/// # }
+/// # fn get_address_for_self<RB: tedge_api::address::ReceiverBundle>(&self) -> Result<tedge_api::Address<RB>, tedge_api::error::DirectoryError> {
+/// # unimplemented!()
+/// # }
+/// # }
+/// #
+/// # let plugin_dir: PD = { unimplemented!() };
+/// # let plugin_dir = &plugin_dir;
+/// #
+/// // The configuration of the plugin contains a number of addresses to send to
+/// #[derive(serde::Deserialize)]
+/// struct Config {
+/// addresses: tedge_lib::config::OneOrMany<tedge_lib::config::Address>,
+/// }
+/// #
+/// # let config = r#"
+/// # addresses = ["foo"]
+/// # "#;
+/// #
+/// # let config: Config = toml::from_str(config).unwrap();
+///
+/// use tedge_lib::address::AddressGroup;
+/// use futures::stream::StreamExt;
+///
+/// // The AddressGroup type is built using the plugin directory and the configured addresses
+/// let addrs: AddressGroup<MessageReceiver> = AddressGroup::build(plugin_dir, &config.addresses).unwrap();
+///
+/// // Messages are send using the AddressGroup::send_and_wait() interface, which sends to all
+/// // addresses
+/// # let message = M;
+/// let results = addrs.send_and_wait(message)
+/// .collect::<tedge_lib::iter::SendAllResult<M>>()
+/// .await;
+///
+/// // "results" now contains all successful results as well as all errors
+/// // and these can be processed as required
+/// # };
+/// ```
+pub struct SendAllResult<M: tedge_api::Message> {
+ oks: Vec<tedge_api::address::ReplyReceiverFor<M>>,
+ errs: Vec<M>,
+}
+
+impl<M> Default for SendAllResult<M>
+where
+ M: tedge_api::Message,
+{
+ fn default() -> Self {
+ SendAllResult {
+ oks: Vec::new(),
+ errs: Vec::new(),
+ }
+ }
+}
+
+impl<M> Extend<Result<tedge_api::address::ReplyReceiverFor<M>, M>> for SendAllResult<M>
+where
+ M: tedge_api::Message,
+{
+ fn extend<T: IntoIterator<Item = Result<tedge_api::address::ReplyReceiverFor<M>, M>>>(
+ &mut self,
+ iter: T,
+ ) {
+ for elem in iter {
+ match elem {
+ Ok(ok) => self.oks.push(ok),
+ Err(e) => self.errs.push(e),
+ }
+ }
+ }
+}
+
+impl<M> SendAllResult<M>
+where
+ M: tedge_api::Message,
+{
+ pub fn oks(&self) -> &[tedge_api::address::ReplyReceiverFor<M>] {
+ &self.oks
+ }
+
+ pub fn into_oks(self) -> Vec<tedge_api::address::ReplyReceiverFor<M>> {
+ self.oks
+ }
+
+ pub fn errs(&self) -> &[M] {
+ &self.errs
+ }
+
+ pub fn into_errs(self) -> Vec<M> {
+ self.errs
+ }
+
+ pub fn into_result(self) -> Result<Vec<tedge_api::address::ReplyReceiverFor<M>>, Vec<M>> {
+ if !self.errs().is_empty() {
+ Ok(self.into_oks())
+ } else {
+ Err(self.into_errs())
+ }
+ }
+}