1 use super::{error::Never, Change}; 2 use futures_core::Stream; 3 use pin_project_lite::pin_project; 4 use std::iter::{Enumerate, IntoIterator}; 5 use std::{ 6 pin::Pin, 7 task::{Context, Poll}, 8 }; 9 use tower_service::Service; 10 11 pin_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 25 impl<T, U> ServiceList<T> 26 where 27 T: IntoIterator<Item = U>, 28 { 29 #[allow(missing_docs)] new<Request>(services: T) -> ServiceList<T> where U: Service<Request>,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 40 impl<T, U> Stream for ServiceList<T> 41 where 42 T: IntoIterator<Item = U>, 43 { 44 type Item = Result<Change<usize, U>, Never>; 45 poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>>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)] 57 type ListVecTest<T> = ServiceList<Vec<T>>; 58 59 #[cfg(test)] 60 #[allow(dead_code)] 61 type ListVecIterTest<T> = ServiceList<::std::vec::IntoIter<T>>; 62