predawn-core 0.9.0

Core types and traits for predawn
Documentation
use std::{
    collections::{BTreeMap, BTreeSet},
    error::Error,
    fmt,
};

use http::StatusCode;

use crate::{
    error::BoxError,
    error_ext::{ErrorExt, NextError},
    location::Location,
    openapi::{self, merge_responses, Schema},
    response::Response,
    response_error::ResponseError,
};

#[derive(Debug)]
pub enum Either<L, R> {
    Left(L),
    Right(R),
}

impl<L, R> fmt::Display for Either<L, R>
where
    L: fmt::Display,
    R: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Either::Left(l) => fmt::Display::fmt(l, f),
            Either::Right(r) => fmt::Display::fmt(r, f),
        }
    }
}

impl<L, R> Error for Either<L, R>
where
    L: Error,
    R: Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            Either::Left(l) => l.source(),
            Either::Right(r) => r.source(),
        }
    }
}

impl<L, R> ErrorExt for Either<L, R>
where
    L: ErrorExt,
    R: ErrorExt,
{
    fn entry(&self) -> (Location, NextError<'_>) {
        match self {
            Either::Left(l) => l.entry(),
            Either::Right(r) => r.entry(),
        }
    }
}

impl<L, R> ResponseError for Either<L, R>
where
    L: ResponseError,
    R: ResponseError,
{
    fn as_status(&self) -> StatusCode {
        match self {
            Either::Left(l) => l.as_status(),
            Either::Right(r) => r.as_status(),
        }
    }

    fn status_codes(codes: &mut BTreeSet<StatusCode>) {
        L::status_codes(codes);
        R::status_codes(codes);
    }

    fn as_response(&self) -> Response {
        match self {
            Either::Left(l) => l.as_response(),
            Either::Right(r) => r.as_response(),
        }
    }

    fn responses(
        schemas: &mut BTreeMap<String, Schema>,
        schemas_in_progress: &mut Vec<String>,
    ) -> BTreeMap<StatusCode, openapi::Response> {
        let mut responses = L::responses(schemas, schemas_in_progress);
        merge_responses(&mut responses, R::responses(schemas, schemas_in_progress));
        responses
    }

    #[doc(hidden)]
    fn inner(self) -> BoxError {
        match self {
            Either::Left(l) => l.inner(),
            Either::Right(r) => r.inner(),
        }
    }
}