1use std::error;
19use std::fmt::{Debug, Display};
20
21use http::{HeaderValue, Method, StatusCode};
22
23use crate::utils::try_to_uri;
24
25#[derive(Debug, Clone)]
26pub enum ValueType {
27 Url,
28 HeaderName,
29 HeaderValue,
30 Status,
31 Body,
32}
33
34impl Display for ValueType {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match self {
37 ValueType::Url => write!(f, "Url"),
38 ValueType::HeaderName => write!(f, "Header name"),
39 ValueType::HeaderValue => write!(f, "Header value"),
40 ValueType::Body => write!(f, "Body"),
41 ValueType::Status => write!(f, "Status"),
42 }
43 }
44}
45
46#[derive(Debug, Clone)]
47pub struct Value {
48 pub tpe: ValueType,
49 pub value: Option<String>,
50}
51
52impl Display for Value {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 if let Some(value) = self.value.as_ref() {
55 write!(f, "{}: {}", self.tpe, value)
56 } else {
57 write!(f, "{}", self.tpe)
58 }
59 }
60}
61
62#[derive(Debug, Clone, PartialEq)]
63pub enum PrrType {
64 Request,
65 Response,
66}
67
68#[derive(Debug, Clone)]
69pub enum Error {
70 BadValue(Value),
71 MissingValue(ValueType),
72 BadStatus,
73 InvalidMode,
74}
75
76impl error::Error for Error {}
77
78impl Display for Error {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match &self {
81 Error::BadValue(v) => write!(f, "Bad value: {v}"),
82 Error::BadStatus => write!(f, "Bad Status"),
83 Error::InvalidMode => write!(f, "Invalid mode"),
84 Error::MissingValue(processable_request_response_value_type) => write!(
85 f,
86 "Missing value: {processable_request_response_value_type}"
87 ),
88 }
89 }
90}
91
92pub type Result<T> = std::result::Result<T, Error>;
93
94pub trait Prr<Body>: Debug {
96 fn headers(&self) -> Vec<(String, HeaderValue)>;
99 fn set_header_value(&mut self, header: &str, value: &str) -> Result<()>;
100 fn clear_headers(&mut self) -> Result<()>;
101 fn remove_header(&mut self, header: &str) -> Result<()>;
102 fn add_header(&mut self, header: &str, value: &str) -> Result<()>;
103
104 fn url(&self) -> Result<url::Url>;
107 fn set_url(&mut self, url: &url::Url) -> Result<()>;
108
109 fn set_status(&mut self, response: &u16) -> Result<()>;
112 fn get_status(&self) -> Result<StatusCode>;
113
114 fn set_body(&mut self, body: &Body) -> Result<()>;
117 fn get_body(&self) -> Result<&Body>;
118
119 fn set_method(&mut self, method: &Method) -> Result<()>;
122 fn get_method(&self) -> Method;
123
124 fn tpe(&self) -> PrrType;
126}
127
128impl TryFrom<&dyn Prr<Vec<u8>>> for http::Request<Vec<u8>> {
129 type Error = Error;
130
131 fn try_from(value: &dyn Prr<Vec<u8>>) -> std::result::Result<Self, Self::Error> {
132 if value.tpe() != PrrType::Request {
133 return Err(Error::InvalidMode);
134 }
135
136 let mut request_builder = http::request::Builder::new();
137
138 for (header_key, header_value) in value.headers() {
140 request_builder = request_builder.header(header_key, header_value);
141 }
142
143 let url = value
144 .url()
145 .map_err(|_| Error::MissingValue(ValueType::Url))?;
146
147 request_builder = request_builder.uri(try_to_uri(&url).map_err(|_| {
149 Error::BadValue(Value {
150 tpe: ValueType::Url,
151 value: Some(url.to_string()),
152 })
153 })?);
154
155 request_builder
157 .body(
158 value
159 .get_body()
160 .map_err(|_| Error::MissingValue(ValueType::Body))?
161 .clone(),
162 )
163 .map_err(|_| {
164 Error::BadValue(Value {
165 tpe: ValueType::Body,
166 value: None,
167 })
168 })
169 }
170}
171impl TryFrom<&dyn Prr<Vec<u8>>> for http::Response<Vec<u8>> {
172 type Error = Error;
173
174 fn try_from(value: &dyn Prr<Vec<u8>>) -> std::result::Result<Self, Self::Error> {
175 if value.tpe() != PrrType::Response {
176 return Err(Error::InvalidMode);
177 }
178
179 let mut response_builder = http::response::Builder::new();
180
181 for (header_key, header_value) in value.headers() {
183 response_builder = response_builder.header(header_key, header_value);
184 }
185
186 response_builder =
188 response_builder.status(value.get_status().map_err(|_| Error::BadStatus)?);
189
190 response_builder
192 .body(
193 value
194 .get_body()
195 .map_err(|_| Error::MissingValue(ValueType::Body))?
196 .clone(),
197 )
198 .map_err(|_| {
199 Error::BadValue(Value {
200 tpe: ValueType::Body,
201 value: None,
202 })
203 })
204 }
205}