tower/discover/
list.rs

1use super::Change;
2use futures_core::Stream;
3use pin_project_lite::pin_project;
4use std::convert::Infallible;
5use std::iter::{Enumerate, IntoIterator};
6use std::{
7    pin::Pin,
8    task::{Context, Poll},
9};
10use tower_service::Service;
11
12pin_project! {
13    /// Static service discovery based on a predetermined list of services.
14    ///
15    /// [`ServiceList`] is created with an initial list of services. The discovery
16    /// process will yield this list once and do nothing after.
17    #[derive(Debug)]
18    pub struct ServiceList<T>
19    where
20        T: IntoIterator,
21    {
22        inner: Enumerate<T::IntoIter>,
23    }
24}
25
26impl<T, U> ServiceList<T>
27where
28    T: IntoIterator<Item = U>,
29{
30    #[allow(missing_docs)]
31    pub fn new<Request>(services: T) -> ServiceList<T>
32    where
33        U: Service<Request>,
34    {
35        ServiceList {
36            inner: services.into_iter().enumerate(),
37        }
38    }
39}
40
41impl<T, U> Stream for ServiceList<T>
42where
43    T: IntoIterator<Item = U>,
44{
45    type Item = Result<Change<usize, U>, Infallible>;
46
47    fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
48        match self.project().inner.next() {
49            Some((i, service)) => Poll::Ready(Some(Ok(Change::Insert(i, service)))),
50            None => Poll::Ready(None),
51        }
52    }
53}
54
55// check that List can be directly over collections
56#[cfg(test)]
57#[allow(dead_code)]
58type ListVecTest<T> = ServiceList<Vec<T>>;
59
60#[cfg(test)]
61#[allow(dead_code)]
62type ListVecIterTest<T> = ServiceList<::std::vec::IntoIter<T>>;