| use super::{error::Never, Change}; |
| use futures_core::Stream; |
| use pin_project_lite::pin_project; |
| use std::iter::{Enumerate, IntoIterator}; |
| use std::{ |
| pin::Pin, |
| task::{Context, Poll}, |
| }; |
| use tower_service::Service; |
| |
| pin_project! { |
| /// Static service discovery based on a predetermined list of services. |
| /// |
| /// [`ServiceList`] is created with an initial list of services. The discovery |
| /// process will yield this list once and do nothing after. |
| #[derive(Debug)] |
| pub struct ServiceList<T> |
| where |
| T: IntoIterator, |
| { |
| inner: Enumerate<T::IntoIter>, |
| } |
| } |
| |
| impl<T, U> ServiceList<T> |
| where |
| T: IntoIterator<Item = U>, |
| { |
| #[allow(missing_docs)] |
| pub fn new<Request>(services: T) -> ServiceList<T> |
| where |
| U: Service<Request>, |
| { |
| ServiceList { |
| inner: services.into_iter().enumerate(), |
| } |
| } |
| } |
| |
| impl<T, U> Stream for ServiceList<T> |
| where |
| T: IntoIterator<Item = U>, |
| { |
| type Item = Result<Change<usize, U>, Never>; |
| |
| fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> { |
| match self.project().inner.next() { |
| Some((i, service)) => Poll::Ready(Some(Ok(Change::Insert(i, service)))), |
| None => Poll::Ready(None), |
| } |
| } |
| } |
| |
| // check that List can be directly over collections |
| #[cfg(test)] |
| #[allow(dead_code)] |
| type ListVecTest<T> = ServiceList<Vec<T>>; |
| |
| #[cfg(test)] |
| #[allow(dead_code)] |
| type ListVecIterTest<T> = ServiceList<::std::vec::IntoIter<T>>; |