Repository: actix/actix-web
File: src/types/either.rs (Rust)

Code before:
    /// Error from primary extractor.
    A(A),

    /// Error from fallback extractor.
    B(B),
}

impl<A, B> Into<Error> for EitherExtractError<A, B>
where
    A: Into<Error>,
    B: Into<Error>,
{
    fn into(self) -> Error {
        match self {
            EitherExtractError::Bytes(err) => err,
            EitherExtractError::A(err) => err.into(),
            EitherExtractError::B(err) => err.into(),
        }
    }
}

/// Provides a mechanism for trying two extractors, a primary and a fallback. Useful for
/// "polymorphic payloads" where, for example, a form might be JSON or URL encoded.
///
/// It is important to note that this extractor, by necessity, buffers the entire request payload
/// as part of it's implementation. Though, it does respect a `PayloadConfig`'s maximum size limit.
impl<A, B> FromRequest for Either<A, B>
where
    A: FromRequest + 'static,
    B: FromRequest + 'static,
{
    type Error = EitherExtractError<A::Error, B::Error>;
    type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;
    type Config = ();

    fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
        let req2 = req.clone();

        Bytes::from_request(req, payload)
            .map_err(EitherExtractError::Bytes)
            .and_then(|bytes| bytes_to_a_or_b(req2, bytes))
            .boxed_local()
    }
}

async fn bytes_to_a_or_b<A, B>(
    req: HttpRequest,
    bytes: Bytes,
) -> Result<Either<A, B>, EitherExtractError<A::Error, B::Error>>
where
    A: FromRequest + 'static,

Review comment (suggestion):
```suggestion
/// as part of its implementation. Though, it does respect a `PayloadConfig`'s maximum size limit.
```

Code after:
pub enum EitherExtractError<A, B> {
    /// Error from payload buffering, such as exceeding payload max size limit.
    Bytes(Error),

    /// Error from primary extractor.
    Extract(A, B),
}

impl<A, B> Into<Error> for EitherExtractError<A, B>
where
    A: Into<Error>,
    B: Into<Error>,
{
    fn into(self) -> Error {
        match self {
            EitherExtractError::Bytes(err) => err,
            EitherExtractError::Extract(a_err, _b_err) => a_err.into(),
        }
    }
}

/// Provides a mechanism for trying two extractors, a primary and a fallback. Useful for
/// "polymorphic payloads" where, for example, a form might be JSON or URL encoded.
///
/// It is important to note that this extractor, by necessity, buffers the entire request payload
/// as part of its implementation. Though, it does respect a `PayloadConfig`'s maximum size limit.
impl<A, B> FromRequest for Either<A, B>
where
    A: FromRequest + 'static,
    B: FromRequest + 'static,
{
    type Error = EitherExtractError<A::Error, B::Error>;
    type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;
    type Config = ();

    fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
        let req2 = req.clone();

        Bytes::from_request(req, payload)
            .map_err(EitherExtractError::Bytes)
            .and_then(|bytes| bytes_to_a_or_b(req2, bytes))
            .boxed_local()
    }
}

async fn bytes_to_a_or_b<A, B>(
    req: HttpRequest,
    bytes: Bytes,
) -> Result<Either<A, B>, EitherExtractError<A::Error, B::Error>>
where
    A: FromRequest + 'static,