Trait ldap3::adapters::Adapter

source ·
pub trait Adapter<'a, S, A>: AdapterClone<'a, S, A> + Debug + Send + Sync + 'a {
    // Required methods
    fn start<'life0, 'life1, 'life2, 'life3, 'async_trait>(
        &'life0 mut self,
        stream: &'life1 mut SearchStream<'a, S, A>,
        base: &'life2 str,
        scope: Scope,
        filter: &'life3 str,
        attrs: A
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'a: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait;
    fn next<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        stream: &'life1 mut SearchStream<'a, S, A>
    ) -> Pin<Box<dyn Future<Output = Result<Option<ResultEntry>>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'a: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn finish<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        stream: &'life1 mut SearchStream<'a, S, A>
    ) -> Pin<Box<dyn Future<Output = LdapResult> + Send + 'async_trait>>
       where Self: 'async_trait,
             'a: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
}
Expand description

Adapter interface to a Search.

Structs implementing this trait:

  • Must additionally implement Clone and Debug;

  • Must be Send and Sync.

The trait is parametrized with 'a, the lifetime bound propagated to trait objects, S, used in the start() method as the generic type for attribute names, and A, the vector of attribute names. (They appear here because of object safety; A enables initialization with owned or borrowed attribute lists.) When implementing the trait, S must be constrained to AsRef<str> + Send + Sync + 'a, and A to AsRef<[S]> + Send + Sync + 'a. To use a bare instance of a struct implementing this trait in the call to streaming_search_with(), the struct must also implement SoloMarker.

There are three points where an adapter can hook into a Search:

  1. Initialization, which can be used to capture the parameters of the operation itself and the underlying Ldap handle, as well as to prepare the internal adapter state. This is done in the start() method.

  2. Entry iteration, where each fetched entry can be examined, transformed, or discarded. The next() method serves this purpose.

  3. Termination, which can examine and transform the result, or invoke further operations to terminate other active connections or operations, if necessary. The finish() method is used for this.

All three methods are called in an async context, so they are marked as async and implemented using the async_trait proc macro from the async-trait crate. To make chaining work, all trait methods must call the corresponding method on the passed stream handle.

Additional details of the calling structure are provided in the documentation of the StreamState enum.

§Example: the EntriesOnly adapter

This adapter discards intermediate messages and collects all referreals in the result of the Search operation. The (slightly simplified) source is annotated by comments pointing out the notable details of the implementation.

// An adapter must implement Clone and Debug
#[derive(Clone, Debug)]
pub struct EntriesOnly {
    refs: Vec<String>,
}

// This impl enables the use of a bare struct instance
// when invoking a Search
impl SoloMarker for EntriesOnly {}

// Adapter impl must be derived with the async_trait proc macro
// until Rust supports async fns in traits directly
#[async_trait]
impl<'a, S, A> Adapter<'a, S, A> for EntriesOnly
where
    // The S and A generic parameters must have these bounds
    S: AsRef<str> + Send + Sync + 'a,
    A: AsRef<[S]> + Send + Sync + 'a,
{
    // The start() method doesn't do much
    async fn start(
        &mut self,
        stream: &mut SearchStream<'a, S, A>,
        base: &str,
        scope: Scope,
        filter: &str,
        attrs: A,
    ) -> Result<()> {
        self.refs.clear();
        // Call up the adapter chain
        stream.start(base, scope, filter, attrs).await
    }

    // Multiple calls up the chain are possible before
    // a single result entry is returned
    async fn next(
        &mut self,
        stream: &mut SearchStream<'a, S, A>
    ) -> Result<Option<ResultEntry>> {
        loop {
            // Call up the adapter chain
            return match stream.next().await {
                Ok(None) => Ok(None),
                Ok(Some(re)) => {
                    if re.is_intermediate() {
                        continue;
                    } else if re.is_ref() {
                        self.refs.extend(parse_refs(re.0));
                        continue;
                    } else {
                        Ok(Some(re))
                    }
                }
                Err(e) => Err(e),
            };
        }
    }

    // The result returned from the upcall is modified by our values
    async fn finish(&mut self, stream: &mut SearchStream<'a, S, A>) -> LdapResult {
        // Call up the adapter chain
        let mut res = stream.finish().await;
        res.refs.extend(std::mem::take(&mut self.refs));
        res
    }
}

Required Methods§

source

fn start<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 mut self, stream: &'life1 mut SearchStream<'a, S, A>, base: &'life2 str, scope: Scope, filter: &'life3 str, attrs: A ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'a: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Initialize the stream.

source

fn next<'life0, 'life1, 'async_trait>( &'life0 mut self, stream: &'life1 mut SearchStream<'a, S, A> ) -> Pin<Box<dyn Future<Output = Result<Option<ResultEntry>>> + Send + 'async_trait>>
where Self: 'async_trait, 'a: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Fetch the next entry from the stream.

source

fn finish<'life0, 'life1, 'async_trait>( &'life0 mut self, stream: &'life1 mut SearchStream<'a, S, A> ) -> Pin<Box<dyn Future<Output = LdapResult> + Send + 'async_trait>>
where Self: 'async_trait, 'a: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Return the result from the stream.

Implementors§

source§

impl<'a, S, A> Adapter<'a, S, A> for EntriesOnly
where S: AsRef<str> + Send + Sync + 'a, A: AsRef<[S]> + Send + Sync + 'a,

source§

impl<'a, S, A> Adapter<'a, S, A> for PagedResults<S, A>
where S: AsRef<str> + Clone + Debug + Send + Sync + 'a, A: AsRef<[S]> + Clone + Debug + Send + Sync + 'a,