use futures_core::ready;
use pin_project::pin_project;
use std::{
pin::Pin,
task::{Context, Poll},
};
use tower_discover::{Change, Discover};
use tower_service::Service;
use crate::Load;
#[pin_project]
#[derive(Debug)]
pub struct Constant<T, M> {
inner: T,
load: M,
}
impl<T, M: Copy> Constant<T, M> {
pub fn new(inner: T, load: M) -> Self {
Self { inner, load }
}
}
impl<T, M: Copy + PartialOrd> Load for Constant<T, M> {
type Metric = M;
fn load(&self) -> M {
self.load
}
}
impl<S, M, Request> Service<Request> for Constant<S, M>
where
S: Service<Request>,
M: Copy,
{
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: Request) -> Self::Future {
self.inner.call(req)
}
}
impl<D: Discover + Unpin, M: Copy> Discover for Constant<D, M> {
type Key = D::Key;
type Service = Constant<D::Service, M>;
type Error = D::Error;
fn poll_discover(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<Change<D::Key, Self::Service>, D::Error>> {
use self::Change::*;
let this = self.project();
let change = match ready!(Pin::new(this.inner).poll_discover(cx))? {
Insert(k, svc) => Insert(k, Constant::new(svc, *this.load)),
Remove(k) => Remove(k),
};
Poll::Ready(Ok(change))
}
}