Skip to content

Commit

Permalink
Wrap panic into results in glossary API
Browse files Browse the repository at this point in the history
Signed-off-by: Avimitin <dev@avimit.in>
  • Loading branch information
Avimitin committed Feb 29, 2024
1 parent 7b2daed commit c623ea6
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 30 deletions.
139 changes: 109 additions & 30 deletions src/endpoint/glossary.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
endpoint::{Error, Result},
endpoint::{Error, Result, REPO_URL},
DeepLApi, Lang,
};
use core::future::IntoFuture;
Expand Down Expand Up @@ -82,21 +82,64 @@ impl<'a> IntoFuture for CreateGlossary<'a> {
let fields = CreateGlossaryRequestParam::from(self);
let fut = async move {
let resp = client
.post(client.get_endpoint("glossaries"))
.json(&fields)
.send()
.await
.map_err(|err| Error::RequestFail(err.to_string()))?
.json::<GlossaryResp>()
.await
.expect("Unmatched response to CreateGlossaryResp, please open issue on https://github.com/Avimitin/deepl.");
Ok(resp)
.post(client.get_endpoint("glossaries"))
.json(&fields)
.send()
.await
.map_err(|err| Error::RequestFail(err.to_string()))?
.json::<GlossaryPossibleResps>()
.await
.unwrap_or_else(|_| {
panic!(
"Unmatched response to CreateGlossaryResp, please open issue on {REPO_URL}."
)
});

match resp {
GlossaryPossibleResps::Fail { message } => Err(Error::RequestFail(format!(
"Fail to create request to glossary API: {message}"
))),
GlossaryPossibleResps::Success {
glossary_id,
name,
ready,
source_lang,
target_lang,
creation_time,
entry_count,
} => Ok(GlossaryResp {
glossary_id,
name,
ready,
source_lang,
target_lang,
creation_time,
entry_count,
}),
}
};

Box::pin(fut)
}
}

#[derive(serde::Deserialize)]
#[serde(untagged)]
enum GlossaryPossibleResps {
Success {
glossary_id: String,
name: String,
ready: bool,
source_lang: Lang,
target_lang: Lang,
creation_time: String,
entry_count: u64,
},
Fail {
message: String,
},
}

#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct GlossaryResp {
/// A unique ID assigned to a glossary.
Expand Down Expand Up @@ -210,24 +253,45 @@ impl DeepLApi {
.map_err(|e| Error::RequestFail(e.to_string()))?
.json::<HashMap<String, Vec<GlossaryResp>>>()
.await
.expect("Unmatched type HashMap<String, Vec<CreateGlossaryResp>> to DeepL response. Please open issue on https://github.com/Avimitin/deepl.")
.map_err(|err| Error::RequestFail(format!("Unexpected error when requesting list_all_glossaries, please open issue on {REPO_URL}: {err}")))?
.remove("glossaries")
.expect("Unmatched DeepL response, expect glossaries key to unwrap. Please open issue on https://github.com/Avimitin/deepl."),
.ok_or(Error::RequestFail(format!("Unable to find key glossaries in response, please open issue on {REPO_URL}")))?
)
}

/// Retrieve meta information for a single glossary, omitting the glossary entries.
/// Require a unique ID assigned to the glossary.
pub async fn retrieve_glossary_details(&self, id: impl ToString) -> Result<GlossaryResp> {
Ok(
self.get(self.get_endpoint(&format!("glossaries/{}", id.to_string())))
.send()
.await
.map_err(|e| Error::RequestFail(e.to_string()))?
.json::<GlossaryResp>()
.await
.expect("Unmatched DeepL response to type GlossaryResp. Please open issue on https://github.com/Avimitin/deepl."),
)
match self
.get(self.get_endpoint(&format!("glossaries/{}", id.to_string())))
.send()
.await
.map_err(|e| Error::RequestFail(e.to_string()))?
.json::<GlossaryPossibleResps>()
.await
.expect("")
{
GlossaryPossibleResps::Fail { message } => Err(Error::RequestFail(format!(
"fail to send request to glossary API: {message}"
))),
GlossaryPossibleResps::Success {
glossary_id,
name,
ready,
source_lang,
target_lang,
creation_time,
entry_count,
} => Ok(GlossaryResp {
glossary_id,
name,
ready,
source_lang,
target_lang,
creation_time,
entry_count,
}),
}
}

/// Deletes the specified glossary.
Expand All @@ -245,33 +309,48 @@ impl DeepLApi {
&self,
id: impl ToString,
) -> Result<Vec<(String, String)>> {
Ok(self.get(self.get_endpoint(&format!("glossaries/{}/entries", id.to_string())))
Ok(self
.get(self.get_endpoint(&format!("glossaries/{}/entries", id.to_string())))
.header("Accept", "text/tab-separated-values")
.send()
.await
.map_err(|e| Error::RequestFail(e.to_string()))?
.text()
.await
.map(|resp| {
resp.split("\n").map(|line| {
let mut pair = line.split("\t");
(pair.next().unwrap().to_string(), pair.next().unwrap().to_string())
}).collect()
resp.split("\n")
.map(|line| {
let mut pair = line.split("\t");
(
pair.next().unwrap().to_string(),
pair.next().unwrap().to_string(),
)
})
.collect()
})
.expect("Fail to retrieve glossary entries. Please open issue on https://github.com/Avimitin/deepl."))
.map_err(|err| {
Error::RequestFail(format!("fail to retrieve glossary entries: {err}"))
}))?
}

/// Retrieve the list of language pairs supported by the glossary feature.
pub async fn list_glossary_language_pairs(&self) -> Result<Vec<GlossaryLanguagePair>> {
Ok(self.get(self.get_endpoint("glossary-language-pairs"))
let pair = self
.get(self.get_endpoint("glossary-language-pairs"))
.send()
.await
.map_err(|e| Error::RequestFail(e.to_string()))?
.json::<HashMap<String, Vec<GlossaryLanguagePair>>>()
.await
.expect("Fail to parse DeepL response for glossary language pair, Please open issue on https://github.com/Avimitin/deepl.")
.map_err(|err| {
Error::RequestFail(format!("fail to list glossary language pairs: {err}"))
})?
.remove("supported_languages")
.expect("Fail to get supported languages from glossary language pairs"))
.ok_or(Error::RequestFail(format!(
"Fail to get supported languages from glossary language pairs"
)))?;

Ok(pair)
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/endpoint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub enum Error {
WriteFileError(String),
}

const REPO_URL: &'static str = "https://github.com/Avimitin/deepl-rs";

/// Alias Result<T, E> to Result<T, [`Error`]>
type Result<T, E = Error> = std::result::Result<T, E>;

Expand Down

0 comments on commit c623ea6

Please sign in to comment.