tower_discover/
list.rs

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