Skip to content

Commit

Permalink
Merge branch 'master' into simplify-imports
Browse files Browse the repository at this point in the history
Conflicts:
	examples/api_trait_implementation.rs
	src/api.rs
	src/client_reqwest.rs
	src/client_ureq.rs
  • Loading branch information
EdJoPaTo committed Sep 10, 2024
2 parents a6ce270 + 060cba1 commit 6c5e900
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 140 deletions.
38 changes: 23 additions & 15 deletions examples/api_trait_implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,15 @@ impl From<isahc::Error> for Error {
impl TelegramApi for Api {
type Error = Error;

fn request<T1: serde::ser::Serialize, T2: serde::de::DeserializeOwned>(
fn request<Params, Output>(
&self,
method: &str,
params: Option<T1>,
) -> Result<T2, Error> {
params: Option<Params>,
) -> Result<Output, Self::Error>
where
Params: serde::ser::Serialize + std::fmt::Debug,
Output: serde::de::DeserializeOwned,
{
let url = format!("{}/{method}", self.api_url);

let request_builder = Request::post(url).header("Content-Type", "application/json");
Expand All @@ -68,28 +72,32 @@ impl TelegramApi for Api {

let text = response.text().map_err(|error| Error::Http {
code: 500,
message: error.to_string(),
message: format!("{error:?}"),
})?;

let parsed_result: Result<T2, serde_json::Error> = serde_json::from_str(&text);

parsed_result.map_err(|_| match serde_json::from_str::<ErrorResponse>(&text) {
Ok(result) => Error::Api(result),
Err(error) => Error::Http {
code: 500,
message: format!("{error:?}"),
},
serde_json::from_str(&text).map_err(|_| {
match serde_json::from_str::<ErrorResponse>(&text) {
Ok(result) => Error::Api(result),
Err(error) => Error::Http {
code: 500,
message: format!("{error:?}"),
},
}
})
}

// isahc doesn't support multipart uploads
// https://github.com/sagebind/isahc/issues/14
fn request_with_form_data<T1: serde::ser::Serialize, T2: serde::de::DeserializeOwned>(
fn request_with_form_data<Params, Output>(
&self,
_method: &str,
_params: T1,
_params: Params,
_files: Vec<(&str, PathBuf)>,
) -> Result<T2, Error> {
) -> Result<Output, Self::Error>
where
Params: serde::ser::Serialize + std::fmt::Debug,
Output: serde::de::DeserializeOwned,
{
let message = "isahc doesn't support form data requests".to_string();
Err(Error::Http { code: 500, message })
}
Expand Down
66 changes: 30 additions & 36 deletions src/client_reqwest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,21 @@ impl AsyncApi {
}

/// Create a new `AsyncApi`. You can use [`AsyncApi::builder`] for more options.
pub fn new_url<T: Into<String>>(api_url: T) -> Self {
pub fn new_url<S: Into<String>>(api_url: S) -> Self {
Self::builder().api_url(api_url).build()
}

pub fn encode_params<T: serde::ser::Serialize + std::fmt::Debug>(
params: &T,
) -> Result<String, Error> {
pub fn encode_params<Params>(params: &Params) -> Result<String, Error>
where
Params: serde::ser::Serialize + std::fmt::Debug,
{
serde_json::to_string(params).map_err(|e| Error::Encode(format!("{e:?} : {params:?}")))
}

pub async fn decode_response<T: serde::de::DeserializeOwned>(
response: reqwest::Response,
) -> Result<T, Error> {
pub async fn decode_response<Output>(response: reqwest::Response) -> Result<Output, Error>
where
Output: serde::de::DeserializeOwned,
{
let status_code = response.status().as_u16();
match response.text().await {
Ok(message) => {
Expand All @@ -48,11 +50,11 @@ impl AsyncApi {
Err(Error::Api(Self::parse_json(&message)?))
}
}
Err(error) => Err(Error::Decode(error.to_string())),
Err(error) => Err(Error::Decode(format!("{error:?}"))),
}
}

fn parse_json<T: serde::de::DeserializeOwned>(body: &str) -> Result<T, Error> {
fn parse_json<Output: serde::de::DeserializeOwned>(body: &str) -> Result<Output, Error> {
serde_json::from_str(body).map_err(|e| Error::Decode(format!("{e:?} : {body:?}")))
}
}
Expand All @@ -61,44 +63,38 @@ impl AsyncApi {
impl AsyncTelegramApi for AsyncApi {
type Error = Error;

async fn request<
T1: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
T2: serde::de::DeserializeOwned,
>(
async fn request<Params, Output>(
&self,
method: &str,
params: Option<T1>,
) -> Result<T2, Self::Error> {
params: Option<Params>,
) -> Result<Output, Self::Error>
where
Params: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
Output: serde::de::DeserializeOwned,
{
let url = format!("{}/{method}", self.api_url);

let mut prepared_request = self
.client
.post(url)
.header("Content-Type", "application/json");

prepared_request = if let Some(data) = params {
let json_string = Self::encode_params(&data)?;

prepared_request.body(json_string)
} else {
prepared_request
if let Some(params) = params {
let json_string = Self::encode_params(&params)?;
prepared_request = prepared_request.body(json_string);
};

let response = prepared_request.send().await?;
let parsed_response: T2 = Self::decode_response(response).await?;

Ok(parsed_response)
Self::decode_response(response).await
}

async fn request_with_form_data<
T1: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
T2: serde::de::DeserializeOwned,
>(
async fn request_with_form_data<Params, Output>(
&self,
method: &str,
params: T1,
params: Params,
files: Vec<(&str, PathBuf)>,
) -> Result<T2, Self::Error> {
) -> Result<Output, Self::Error>
where
Params: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
Output: serde::de::DeserializeOwned,
{
let json_string = Self::encode_params(&params)?;
let json_struct: Value = serde_json::from_str(&json_string).unwrap();
let file_keys: Vec<&str> = files.iter().map(|(key, _)| *key).collect();
Expand Down Expand Up @@ -136,9 +132,7 @@ impl AsyncTelegramApi for AsyncApi {
let url = format!("{}/{method}", self.api_url);

let response = self.client.post(url).multipart(form).send().await?;
let parsed_response: T2 = Self::decode_response(response).await?;

Ok(parsed_response)
Self::decode_response(response).await
}
}

Expand Down
66 changes: 26 additions & 40 deletions src/client_ureq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,73 +23,62 @@ impl Api {
}

/// Create a new `Api`. You can use [`Api::builder`] for more options.
pub fn new_url<T: Into<String>>(api_url: T) -> Self {
pub fn new_url<S: Into<String>>(api_url: S) -> Self {
Self::builder().api_url(api_url).build()
}

pub fn encode_params<T: serde::ser::Serialize + std::fmt::Debug>(
params: &T,
) -> Result<String, Error> {
pub fn encode_params<Params>(params: &Params) -> Result<String, Error>
where
Params: serde::ser::Serialize + std::fmt::Debug,
{
serde_json::to_string(params).map_err(|e| Error::Encode(format!("{e:?} : {params:?}")))
}

pub fn decode_response<T: serde::de::DeserializeOwned>(response: Response) -> Result<T, Error> {
pub fn decode_response<Output>(response: Response) -> Result<Output, Error>
where
Output: serde::de::DeserializeOwned,
{
match response.into_string() {
Ok(message) => {
let json_result: Result<T, serde_json::Error> = serde_json::from_str(&message);

match json_result {
Ok(result) => Ok(result),
Err(e) => {
let err = Error::Decode(format!("{e:?} : {message:?}"));
Err(err)
}
}
}
Err(e) => {
let err = Error::Decode(format!("Failed to decode response: {e:?}"));
Err(err)
}
Ok(message) => serde_json::from_str(&message)
.map_err(|error| Error::Decode(format!("{error:?} : {message:?}"))),
Err(e) => Err(Error::Decode(format!("Failed to decode response: {e:?}"))),
}
}
}

impl TelegramApi for Api {
type Error = Error;

fn request<T1: serde::ser::Serialize + std::fmt::Debug, T2: serde::de::DeserializeOwned>(
&self,
method: &str,
params: Option<T1>,
) -> Result<T2, Error> {
fn request<Params, Output>(&self, method: &str, params: Option<Params>) -> Result<Output, Error>
where
Params: serde::ser::Serialize + std::fmt::Debug,
Output: serde::de::DeserializeOwned,
{
let url = format!("{}/{method}", self.api_url);
let prepared_request = self
.request_agent
.post(&url)
.set("Content-Type", "application/json");

let response = match params {
None => prepared_request.call()?,
Some(data) => {
let json = Self::encode_params(&data)?;
prepared_request.send_string(&json)?
}
};

let parsed_response: T2 = Self::decode_response(response)?;

Ok(parsed_response)
Self::decode_response(response)
}

fn request_with_form_data<
T1: serde::ser::Serialize + std::fmt::Debug,
T2: serde::de::DeserializeOwned,
>(
fn request_with_form_data<Params, Output>(
&self,
method: &str,
params: T1,
params: Params,
files: Vec<(&str, PathBuf)>,
) -> Result<T2, Error> {
) -> Result<Output, Error>
where
Params: serde::ser::Serialize + std::fmt::Debug,
Output: serde::de::DeserializeOwned,
{
let json_string = Self::encode_params(&params)?;
let json_struct: Value = serde_json::from_str(&json_string).unwrap();
let file_keys: Vec<&str> = files.iter().map(|(key, _)| *key).collect();
Expand Down Expand Up @@ -131,10 +120,7 @@ impl TelegramApi for Api {
&format!("multipart/form-data; boundary={}", form_data.boundary()),
)
.send(form_data)?;

let parsed_response: T2 = Self::decode_response(response)?;

Ok(parsed_response)
Self::decode_response(response)
}
}

Expand Down
52 changes: 26 additions & 26 deletions src/trait_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ pub trait AsyncTelegramApi {
let mut new_params = params.clone();
new_params.media = new_medias;

let files_with_str_names: Vec<(&str, PathBuf)> = files
let files_with_str_names = files
.iter()
.map(|(key, path)| (key.as_str(), path.clone()))
.collect();
Expand Down Expand Up @@ -965,7 +965,7 @@ pub trait AsyncTelegramApi {
let mut new_params = params.clone();
new_params.media = new_media;

let files_with_str_names: Vec<(&str, PathBuf)> = files
let files_with_str_names = files
.iter()
.map(|(key, path)| (key.as_str(), path.clone()))
.collect();
Expand Down Expand Up @@ -1066,7 +1066,7 @@ pub trait AsyncTelegramApi {
let mut new_params = params.clone();
new_params.stickers = new_stickers;

let files_with_str_names: Vec<(&str, PathBuf)> = files
let files_with_str_names = files
.iter()
.map(|(key, path)| (key.as_str(), path.clone()))
.collect();
Expand Down Expand Up @@ -1283,33 +1283,33 @@ pub trait AsyncTelegramApi {
.await
}

async fn request_without_body<T: serde::de::DeserializeOwned>(
&self,
method: &str,
) -> Result<T, Self::Error> {
async fn request_without_body<Output>(&self, method: &str) -> Result<Output, Self::Error>
where
Output: serde::de::DeserializeOwned,
{
let params: Option<()> = None;

self.request(method, params).await
}

async fn request<
T1: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
T2: serde::de::DeserializeOwned,
>(
async fn request<Params, Output>(
&self,
method: &str,
params: Option<T1>,
) -> Result<T2, Self::Error>;
params: Option<Params>,
) -> Result<Output, Self::Error>
where
Params: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
Output: serde::de::DeserializeOwned;

async fn request_with_possible_form_data<
T1: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
T2: serde::de::DeserializeOwned,
>(
async fn request_with_possible_form_data<Params, Output>(
&self,
method_name: &str,
params: T1,
params: Params,
files: Vec<(&str, PathBuf)>,
) -> Result<T2, Self::Error> {
) -> Result<Output, Self::Error>
where
Params: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
Output: serde::de::DeserializeOwned,
{
if files.is_empty() {
self.request(method_name, Some(params)).await
} else {
Expand All @@ -1318,13 +1318,13 @@ pub trait AsyncTelegramApi {
}
}

async fn request_with_form_data<
T1: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
T2: serde::de::DeserializeOwned,
>(
async fn request_with_form_data<Params, Output>(
&self,
method: &str,
params: T1,
params: Params,
files: Vec<(&str, PathBuf)>,
) -> Result<T2, Self::Error>;
) -> Result<Output, Self::Error>
where
Params: serde::ser::Serialize + std::fmt::Debug + std::marker::Send,
Output: serde::de::DeserializeOwned;
}
Loading

0 comments on commit 6c5e900

Please sign in to comment.