openapi-contract 0.1.1

Compile-time OpenAPI contract checking for Rust HTTP clients. Validates paths, parameters, and response types against your OpenAPI spec at macro expansion.
Documentation
use std::future::Future;

use crate::error::ApiError;
use crate::sse::SseStream;

/// HTTP method for API requests.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Method {
    GET,
    POST,
    PUT,
    DELETE,
    PATCH,
    HEAD,
    OPTIONS,
}

impl Method {
    pub fn as_reqwest(&self) -> reqwest::Method {
        match self {
            Self::GET => reqwest::Method::GET,
            Self::POST => reqwest::Method::POST,
            Self::PUT => reqwest::Method::PUT,
            Self::DELETE => reqwest::Method::DELETE,
            Self::PATCH => reqwest::Method::PATCH,
            Self::HEAD => reqwest::Method::HEAD,
            Self::OPTIONS => reqwest::Method::OPTIONS,
        }
    }
}

/// Trait for making async API requests.
///
/// Implement this for your HTTP client (e.g. a wrapper around `reqwest::Client`).
pub trait ApiClient: Send + Sync {
    fn request(
        &self,
        method: Method,
        path: &str,
        query: Option<&str>,
        body: Option<String>,
    ) -> impl Future<Output = Result<reqwest::Response, ApiError>> + Send;

    fn request_stream(
        &self,
        method: Method,
        path: &str,
        query: Option<&str>,
    ) -> impl Future<Output = Result<SseStream, ApiError>> + Send;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn method_conversions_and_traits() {
        // as_reqwest covers all variants
        assert_eq!(Method::GET.as_reqwest(), reqwest::Method::GET);
        assert_eq!(Method::POST.as_reqwest(), reqwest::Method::POST);
        assert_eq!(Method::PUT.as_reqwest(), reqwest::Method::PUT);
        assert_eq!(Method::DELETE.as_reqwest(), reqwest::Method::DELETE);
        assert_eq!(Method::PATCH.as_reqwest(), reqwest::Method::PATCH);
        assert_eq!(Method::HEAD.as_reqwest(), reqwest::Method::HEAD);
        assert_eq!(Method::OPTIONS.as_reqwest(), reqwest::Method::OPTIONS);

        // Debug, Eq, Copy
        assert_eq!(format!("{:?}", Method::GET), "GET");
        assert_eq!(Method::GET, Method::GET);
        assert_ne!(Method::GET, Method::POST);
        let m = Method::PUT;
        let m2 = m;
        assert_eq!(m, m2);
    }
}