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