tower/discover/
list.rs

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