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