diff options
author | Cyborus <cyborus@cyborus.xyz> | 2024-02-09 16:58:44 +0100 |
---|---|---|
committer | Cyborus <cyborus@cyborus.xyz> | 2024-02-09 20:37:43 +0100 |
commit | cb1f2d9ae86223c18af43885eb62800963496e34 (patch) | |
tree | 7ea352e52f56575b0a86a608739684a0330d3aba /src | |
parent | more general dereferencing (diff) | |
download | forgejo-api-cb1f2d9ae86223c18af43885eb62800963496e34.tar.xz forgejo-api-cb1f2d9ae86223c18af43885eb62800963496e34.zip |
strongly typed header returns
Diffstat (limited to 'src')
-rw-r--r-- | src/generated.rs | 248 | ||||
-rw-r--r-- | src/lib.rs | 17 |
2 files changed, 258 insertions, 7 deletions
diff --git a/src/generated.rs b/src/generated.rs index ac42f78..544b4d6 100644 --- a/src/generated.rs +++ b/src/generated.rs @@ -1818,13 +1818,13 @@ impl crate::Forgejo { owner: &str, repo: &str, query: RepoGetAllCommitsQuery, - ) -> Result<(reqwest::header::HeaderMap, Vec<Commit>), ForgejoError> { + ) -> Result<(CommitListHeaders, Vec<Commit>), ForgejoError> { let request = self .get(&format!("repos/{owner}/{repo}/commits?{query}")) .build()?; let response = self.execute(request).await?; match response.status().as_u16() { - 200 => Ok((response.headers().clone(), response.json().await?)), + 200 => Ok((response.headers().try_into()?, response.json().await?)), _ => Err(ForgejoError::UnexpectedStatusCode(response.status())), } } @@ -4471,7 +4471,7 @@ impl crate::Forgejo { repo: &str, index: u64, query: RepoGetPullRequestCommitsQuery, - ) -> Result<(reqwest::header::HeaderMap, Vec<Commit>), ForgejoError> { + ) -> Result<(CommitListHeaders, Vec<Commit>), ForgejoError> { let request = self .get(&format!( "repos/{owner}/{repo}/pulls/{index}/commits?{query}" @@ -4479,7 +4479,7 @@ impl crate::Forgejo { .build()?; let response = self.execute(request).await?; match response.status().as_u16() { - 200 => Ok((response.headers().clone(), response.json().await?)), + 200 => Ok((response.headers().try_into()?, response.json().await?)), _ => Err(ForgejoError::UnexpectedStatusCode(response.status())), } } @@ -4495,13 +4495,13 @@ impl crate::Forgejo { repo: &str, index: u64, query: RepoGetPullRequestFilesQuery, - ) -> Result<(reqwest::header::HeaderMap, Vec<ChangedFile>), ForgejoError> { + ) -> Result<(ChangedFileListHeaders, Vec<ChangedFile>), ForgejoError> { let request = self .get(&format!("repos/{owner}/{repo}/pulls/{index}/files?{query}")) .build()?; let response = self.execute(request).await?; match response.status().as_u16() { - 200 => Ok((response.headers().clone(), response.json().await?)), + 200 => Ok((response.headers().try_into()?, response.json().await?)), _ => Err(ForgejoError::UnexpectedStatusCode(response.status())), } } @@ -7217,6 +7217,7 @@ impl crate::Forgejo { } use structs::*; pub mod structs { + use crate::StructureError; /// APIError is an api error with a message /// #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -9623,6 +9624,241 @@ pub mod structs { pub title: Option<String>, } + pub struct ChangedFileListHeaders { + pub x_has_more: Option<bool>, + pub x_page: Option<u64>, + pub x_page_count: Option<u64>, + pub x_per_page: Option<u64>, + pub x_total: Option<u64>, + } + + impl TryFrom<&reqwest::header::HeaderMap> for ChangedFileListHeaders { + type Error = StructureError; + + fn try_from(value: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> { + let x_has_more = value + .get("X-HasMore") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<bool>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_page = value + .get("X-Page") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_page_count = value + .get("X-PageCount") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_per_page = value + .get("X-PerPage") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_total = value + .get("X-Total") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + Ok(Self { + x_has_more, + x_page, + x_page_count, + x_per_page, + x_total, + }) + } + } + + pub struct CommitListHeaders { + pub x_has_more: Option<bool>, + pub x_page: Option<u64>, + pub x_page_count: Option<u64>, + pub x_per_page: Option<u64>, + pub x_total: Option<u64>, + } + + impl TryFrom<&reqwest::header::HeaderMap> for CommitListHeaders { + type Error = StructureError; + + fn try_from(value: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> { + let x_has_more = value + .get("X-HasMore") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<bool>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_page = value + .get("X-Page") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_page_count = value + .get("X-PageCount") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_per_page = value + .get("X-PerPage") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + let x_total = value + .get("X-Total") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + s.parse::<u64>() + .map_err(|_| StructureError::HeaderParseFailed) + }) + .transpose()?; + Ok(Self { + x_has_more, + x_page, + x_page_count, + x_per_page, + x_total, + }) + } + } + + pub struct ErrorHeaders { + pub message: Option<String>, + pub url: Option<String>, + } + + impl TryFrom<&reqwest::header::HeaderMap> for ErrorHeaders { + type Error = StructureError; + + fn try_from(value: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> { + let message = value + .get("message") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.to_string()) + }) + .transpose()?; + let url = value + .get("url") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.to_string()) + }) + .transpose()?; + Ok(Self { message, url }) + } + } + + pub struct ForbiddenHeaders { + pub message: Option<String>, + pub url: Option<String>, + } + + impl TryFrom<&reqwest::header::HeaderMap> for ForbiddenHeaders { + type Error = StructureError; + + fn try_from(value: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> { + let message = value + .get("message") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.to_string()) + }) + .transpose()?; + let url = value + .get("url") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.to_string()) + }) + .transpose()?; + Ok(Self { message, url }) + } + } + + pub struct InvalidTopicsErrorHeaders { + pub invalid_topics: Option<Vec<String>>, + pub message: Option<String>, + } + + impl TryFrom<&reqwest::header::HeaderMap> for InvalidTopicsErrorHeaders { + type Error = StructureError; + + fn try_from(value: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> { + let invalid_topics = value + .get("invalidTopics") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.split(",").map(|s| s.to_string()).collect::<Vec<_>>()) + }) + .transpose()?; + let message = value + .get("message") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.to_string()) + }) + .transpose()?; + Ok(Self { + invalid_topics, + message, + }) + } + } + + pub struct ValidationErrorHeaders { + pub message: Option<String>, + pub url: Option<String>, + } + + impl TryFrom<&reqwest::header::HeaderMap> for ValidationErrorHeaders { + type Error = StructureError; + + fn try_from(value: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> { + let message = value + .get("message") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.to_string()) + }) + .transpose()?; + let url = value + .get("url") + .map(|s| -> Result<_, _> { + let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?; + Ok(s.to_string()) + }) + .transpose()?; + Ok(Self { message, url }) + } + } + pub struct AdminCronListQuery { pub page: Option<u32>, pub limit: Option<u32>, @@ -23,7 +23,7 @@ pub enum ForgejoError { #[error("API key should be ascii")] KeyNotAscii, #[error("the response from forgejo was not properly structured")] - BadStructure(#[source] serde_json::Error, String), + BadStructure(#[from] StructureError), #[error("unexpected status code {} {}", .0.as_u16(), .0.canonical_reason().unwrap_or(""))] UnexpectedStatusCode(StatusCode), #[error("{} {}{}", .0.as_u16(), .0.canonical_reason().unwrap_or(""), .1.as_ref().map(|s| format!(": {s}")).unwrap_or_default())] @@ -32,6 +32,21 @@ pub enum ForgejoError { AuthTooLong, } +#[derive(thiserror::Error, Debug)] +pub enum StructureError { + #[error("{contents}")] + Serde { + e: serde_json::Error, + contents: String, + }, + #[error("failed to find header `{0}`")] + HeaderMissing(&'static str), + #[error("header was not ascii")] + HeaderNotAscii, + #[error("failed to parse header")] + HeaderParseFailed, +} + /// Method of authentication to connect to the Forgejo host with. pub enum Auth<'a> { /// Application Access Token. Grants access to scope enabled for the |