nyquest_interface/blocking/
any.rs

1//! Type-erased blocking client interface traits.
2//!
3//! This module provides trait definitions for type-erased blocking HTTP client
4//! implementations, allowing different backend implementations to be used interchangeably.
5//!
6//! The traits in this module are automatically implemented for types that implement the
7//! corresponding traits from the `blocking::backend` module, so backend developers don't need
8//! to implement them directly.
9
10use std::fmt;
11use std::{any::Any, io};
12
13use super::backend::BlockingResponse;
14use super::Request;
15use crate::client::{BuildClientResult, ClientOptions};
16
17/// Trait for type-erased blocking backend implementations.
18///
19/// Automatically implemented for types implementing `BlockingBackend`.
20pub trait AnyBlockingBackend: Send + Sync + 'static {
21    /// Creates a new blocking client with the given options.
22    fn create_blocking_client(
23        &self,
24        options: ClientOptions,
25    ) -> BuildClientResult<Box<dyn AnyBlockingClient>>;
26}
27
28/// Trait for type-erased blocking HTTP clients.
29///
30/// Automatically implemented for types implementing `BlockingClient`.
31pub trait AnyBlockingClient: Any + Send + Sync + 'static {
32    /// Provides a textual description of this client.
33    fn describe(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
34    /// Creates a cloned boxed version of this client.
35    fn clone_boxed(&self) -> Box<dyn AnyBlockingClient>;
36    /// Sends an HTTP request and returns the response.
37    fn request(&self, req: Request) -> crate::Result<Box<dyn AnyBlockingResponse>>;
38}
39
40/// Trait for type-erased blocking HTTP responses.
41///
42/// Automatically implemented for types implementing `BlockingResponse`.
43/// It extends io::Read to allow streaming the response body.
44pub trait AnyBlockingResponse: io::Read + Any + Send + Sync + 'static {
45    /// Provides a textual description of this response.
46    fn describe(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
47    /// Returns the HTTP status code of this response.
48    fn status(&self) -> u16;
49    /// Returns the content-length of the response body, if known.
50    fn content_length(&self) -> Option<u64>;
51    /// Gets all values for the specified header.
52    fn get_header(&self, header: &str) -> crate::Result<Vec<String>>;
53    /// Reads the response body as text.
54    fn text(&mut self) -> crate::Result<String>;
55    /// Reads the response body as bytes.
56    fn bytes(&mut self) -> crate::Result<Vec<u8>>;
57}
58
59// These implementations allow backend types implementing the base traits
60// to be used with the type-erased trait system automatically.
61
62impl<B> AnyBlockingBackend for B
63where
64    B: super::backend::BlockingBackend,
65{
66    fn create_blocking_client(
67        &self,
68        options: ClientOptions,
69    ) -> BuildClientResult<Box<dyn AnyBlockingClient>> {
70        Ok(Box::new(self.create_blocking_client(options)?))
71    }
72}
73
74impl<R> AnyBlockingResponse for R
75where
76    R: BlockingResponse,
77{
78    fn describe(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        BlockingResponse::describe(self, f)
80    }
81
82    fn status(&self) -> u16 {
83        BlockingResponse::status(self)
84    }
85
86    fn content_length(&self) -> Option<u64> {
87        BlockingResponse::content_length(self)
88    }
89
90    fn get_header(&self, header: &str) -> crate::Result<Vec<String>> {
91        BlockingResponse::get_header(self, header)
92    }
93
94    fn text(&mut self) -> crate::Result<String> {
95        BlockingResponse::text(self)
96    }
97
98    fn bytes(&mut self) -> crate::Result<Vec<u8>> {
99        BlockingResponse::bytes(self)
100    }
101}
102
103impl<B> AnyBlockingClient for B
104where
105    B: super::backend::BlockingClient,
106{
107    fn describe(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        super::backend::BlockingClient::describe(self, f)
109    }
110    fn clone_boxed(&self) -> Box<dyn AnyBlockingClient> {
111        Box::new(self.clone())
112    }
113    fn request(&self, req: Request) -> crate::Result<Box<dyn AnyBlockingResponse>> {
114        Ok(Box::new(self.request(req)?))
115    }
116}