Repository: meilisearch/meilisearch
File: meilisearch/src/extractors/payload.rs (Rust)

Code before:

    type Future = Ready<Result<Payload, Self::Error>>;

    #[inline]
    fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
        let limit = req
            .app_data::<PayloadConfig>()
            .map(|c| c.limit)
            .unwrap_or(PayloadConfig::default().limit);
        ready(Ok(Payload {
            payload: Decompress::from_headers(payload.take(), req.headers()),
            limit,
        }))
    }
}

impl Stream for Payload {
    type Item = Result<web::Bytes, MeilisearchHttpError>;

    #[inline]
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        match Pin::new(&mut self.payload).poll_next(cx) {
            Poll::Ready(Some(result)) => match result {
                Ok(bytes) => match self.limit.checked_sub(bytes.len()) {
                    Some(new_limit) => {
                        self.limit = new_limit;
                        Poll::Ready(Some(Ok(bytes)))
                    }
                    None => {
                        Poll::Ready(Some(Err(MeilisearchHttpError::PayloadTooLarge(self.limit))))
                    }
                },
                x => Poll::Ready(Some(x.map_err(MeilisearchHttpError::from))),
            },
            otherwise => otherwise.map(|o| o.map(|o| o.map_err(MeilisearchHttpError::from))),
        }
    }
}


Review comment (suggestion):
Unfortunately, as you can see, we decrease the `limit` we previously stored in the `Payload` struct. You'll probably have to rename the `limit` field into `remaining` and decrement it. But also introduce a new `limit` field that is never modified and that you'll have to use in the error variant (as you have already done).

Code after:
    type Error = MeilisearchHttpError;

    type Future = Ready<Result<Payload, Self::Error>>;

    #[inline]
    fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
        let limit = req
            .app_data::<PayloadConfig>()
            .map(|c| c.limit)
            .unwrap_or(PayloadConfig::default().limit);
        ready(Ok(Payload {
            payload: Decompress::from_headers(payload.take(), req.headers()),
            limit,
            remaining: limit,
        }))
    }
}

impl Stream for Payload {
    type Item = Result<web::Bytes, MeilisearchHttpError>;

    #[inline]
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        match Pin::new(&mut self.payload).poll_next(cx) {
            Poll::Ready(Some(result)) => match result {
                Ok(bytes) => match self.remaining.checked_sub(bytes.len()) {
                    Some(new_limit) => {
                        self.remaining = new_limit;
                        Poll::Ready(Some(Ok(bytes)))
                    }
                    None => {
                        Poll::Ready(Some(Err(MeilisearchHttpError::PayloadTooLarge(self.limit))))
                    }
                },
                x => Poll::Ready(Some(x.map_err(MeilisearchHttpError::from))),
            },
            otherwise => otherwise.map(|o| o.map(|o| o.map_err(MeilisearchHttpError::from))),
        }
    }
}