pub trait SomeBackendContextBuilderMapper<CB>
where Self: BackendContextBuilder, Self::Context: AsRef<Option<CB::Context>> + 'static, CB: BackendContextBuilder, CB::Context: BackendContext + 'static,
{
Show 19 methods // Provided methods fn map_feature<T: ?Sized + 'static>( &self, f: Option<BackendFeature<CB::Context, T>> ) -> Option<BackendFeature<Self::Context, T>> { ... } fn add_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn AddFolder>> { ... } fn list_folders_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn ListFolders>> { ... } fn expunge_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn ExpungeFolder>> { ... } fn purge_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn PurgeFolder>> { ... } fn delete_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn DeleteFolder>> { ... } fn get_envelope_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn GetEnvelope>> { ... } fn list_envelopes_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn ListEnvelopes>> { ... } fn watch_envelopes_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn WatchEnvelopes>> { ... } fn add_flags_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn AddFlags>> { ... } fn set_flags_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn SetFlags>> { ... } fn remove_flags_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn RemoveFlags>> { ... } fn add_message_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn AddMessage>> { ... } fn send_message_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn SendMessage>> { ... } fn peek_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn PeekMessages>> { ... } fn get_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn GetMessages>> { ... } fn copy_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn CopyMessages>> { ... } fn move_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn MoveMessages>> { ... } fn delete_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn DeleteMessages>> { ... }
}
Expand description

Map a backend feature from subcontext B to context A.

This is useful when you have a context composed of multiple subcontexts. It prevents you to manually map the feature.

See a usage example at ../../tests/dynamic_backend.rs.

use async_trait::async_trait;
use email::{
    account::config::{passwd::PasswdConfig, AccountConfig},
    backend::{
        context::BackendContextBuilder, feature::BackendFeature, macros::BackendContext,
        mapper::SomeBackendContextBuilderMapper, pool::BackendPool, BackendBuilder,
    },
    folder::{list::ListFolders, Folder, FolderKind},
    imap::{
        config::{ImapAuthConfig, ImapConfig, ImapEncryptionKind},
        ImapContextBuilder, ImapContextSync,
    },
    smtp::{SmtpContextBuilder, SmtpContextSync},
    Result,
};
use secret::Secret;
use std::sync::Arc;

#[tokio::test]
async fn test_dynamic_backend() {
    env_logger::builder().is_test(true).init();

    let account_config = Arc::new(AccountConfig::default());

    let imap_config = Arc::new(ImapConfig {
        host: "localhost".into(),
        port: 3143,
        encryption: Some(ImapEncryptionKind::None),
        login: "bob@localhost".into(),
        auth: ImapAuthConfig::Passwd(PasswdConfig(Secret::new_raw("password"))),
        ..Default::default()
    });

    // 1. define custom context

    #[derive(BackendContext)]
    struct DynamicContext {
        imap: Option<ImapContextSync>,
        smtp: Option<SmtpContextSync>,
    }

    // 2. implement AsRef for mapping features

    impl AsRef<Option<ImapContextSync>> for DynamicContext {
        fn as_ref(&self) -> &Option<ImapContextSync> {
            &self.imap
        }
    }

    impl AsRef<Option<SmtpContextSync>> for DynamicContext {
        fn as_ref(&self) -> &Option<SmtpContextSync> {
            &self.smtp
        }
    }

    // 3. define custom context builder

    #[derive(Clone)]
    struct DynamicContextBuilder {
        imap: Option<ImapContextBuilder>,
        smtp: Option<SmtpContextBuilder>,
    }

    // 4. implement backend context builder

    #[async_trait]
    impl BackendContextBuilder for DynamicContextBuilder {
        type Context = DynamicContext;

        // override the list folders feature using the imap builder
        fn list_folders(&self) -> Option<BackendFeature<Self::Context, dyn ListFolders>> {
            self.list_folders_with_some(&self.imap)
        }

        async fn build(self) -> Result<Self::Context> {
            let imap = match self.imap {
                Some(imap) => Some(imap.build().await?),
                None => None,
            };

            let smtp = match self.smtp {
                Some(smtp) => Some(smtp.build().await?),
                None => None,
            };

            Ok(DynamicContext { imap, smtp })
        }
    }

    // 5. plug all together

    let ctx_builder = DynamicContextBuilder {
        imap: Some(ImapContextBuilder::new(
            account_config.clone(),
            imap_config.clone(),
        )),
        smtp: None,
    };
    let backend_builder = BackendBuilder::new(account_config.clone(), ctx_builder);
    let backend: BackendPool<DynamicContext> = backend_builder.build().await.unwrap();
    let folders = backend.list_folders().await.unwrap();

    assert!(folders.contains(&Folder {
        kind: Some(FolderKind::Inbox),
        name: "INBOX".into(),
        desc: "".into()
    }));
}

Provided Methods§

source

fn map_feature<T: ?Sized + 'static>( &self, f: Option<BackendFeature<CB::Context, T>> ) -> Option<BackendFeature<Self::Context, T>>

source

fn add_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn AddFolder>>

source

fn list_folders_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn ListFolders>>

source

fn expunge_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn ExpungeFolder>>

source

fn purge_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn PurgeFolder>>

source

fn delete_folder_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn DeleteFolder>>

source

fn get_envelope_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn GetEnvelope>>

source

fn list_envelopes_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn ListEnvelopes>>

source

fn watch_envelopes_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn WatchEnvelopes>>

source

fn add_flags_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn AddFlags>>

source

fn set_flags_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn SetFlags>>

source

fn remove_flags_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn RemoveFlags>>

source

fn add_message_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn AddMessage>>

source

fn send_message_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn SendMessage>>

source

fn peek_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn PeekMessages>>

source

fn get_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn GetMessages>>

source

fn copy_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn CopyMessages>>

source

fn move_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn MoveMessages>>

source

fn delete_messages_with_some( &self, cb: &Option<CB> ) -> Option<BackendFeature<Self::Context, dyn DeleteMessages>>

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<CB1, CB2> SomeBackendContextBuilderMapper<CB2> for CB1
where CB1: BackendContextBuilder, CB1::Context: AsRef<Option<CB2::Context>> + 'static, CB2: BackendContextBuilder, CB2::Context: BackendContext + 'static,

Automatically implement SomeBackendContextBuilderMapper.