use std::borrow::Cow;
use std::fmt::{Debug, Formatter};
use serde::{Deserialize, Serialize};
use crate::client::DEFAULT_ROWS;
use crate::data::{FedoraRelease, Release};
use crate::error::QueryError;
use crate::request::{PaginatedRequest, Pagination, RequestMethod, SingleRequest};
#[derive(Debug)]
pub struct ReleaseNameQuery<'a> {
name: Cow<'a, str>,
}
impl<'a> ReleaseNameQuery<'a> {
pub fn new(name: &'a str) -> Self {
ReleaseNameQuery {
name: Cow::Borrowed(name),
}
}
pub fn from_release(release: &FedoraRelease) -> Self {
ReleaseNameQuery {
name: Cow::Owned(release.to_string()),
}
}
}
impl<'a> SingleRequest<Release, Release> for ReleaseNameQuery<'a> {
fn method(&self) -> RequestMethod {
RequestMethod::GET
}
fn path(&self) -> Result<String, QueryError> {
Ok(format!("/releases/{}", self.name))
}
fn parse(&self, string: &str) -> Result<Release, QueryError> {
let page: Release = serde_json::from_str(string)?;
Ok(page)
}
fn extract(&self, page: Release) -> Release {
page
}
}
#[derive(Default)]
pub struct ReleaseQuery<'a> {
exclude_archived: Option<bool>,
ids: Option<&'a [&'a str]>,
name: Option<&'a str>,
packages: Option<&'a [&'a str]>,
updates: Option<&'a [&'a str]>,
rows_per_page: u32,
callback: Option<Box<dyn Fn(u32, u32) + 'a>>,
}
impl<'a> Debug for ReleaseQuery<'a> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_struct("ReleaseQuery")
.field("exclude_archived", &self.exclude_archived)
.field("ids", &self.ids)
.field("name", &self.name)
.field("packages", &self.packages)
.field("updates", &self.updates)
.field("rows_per_page", &self.rows_per_page)
.field("callback", &"(function pointer)")
.finish()
}
}
impl<'a> ReleaseQuery<'a> {
pub fn new() -> Self {
ReleaseQuery {
rows_per_page: DEFAULT_ROWS,
..Default::default()
}
}
#[must_use]
pub fn rows_per_page(mut self, rows_per_page: u32) -> Self {
self.rows_per_page = rows_per_page;
self
}
#[must_use]
pub fn callback(mut self, fun: impl Fn(u32, u32) + 'a) -> Self {
self.callback = Some(Box::new(fun));
self
}
#[must_use]
pub fn exclude_archived(mut self, exclude_archived: bool) -> Self {
self.exclude_archived = Some(exclude_archived);
self
}
#[must_use]
pub fn ids(mut self, ids: &'a [&'a str]) -> Self {
self.ids = Some(ids);
self
}
#[must_use]
pub fn name(mut self, name: &'a str) -> Self {
self.name = Some(name);
self
}
#[must_use]
pub fn packages(mut self, packages: &'a [&'a str]) -> Self {
self.packages = Some(packages);
self
}
#[must_use]
pub fn updates(mut self, updates: &'a [&'a str]) -> Self {
self.updates = Some(updates);
self
}
}
#[derive(Debug, Serialize)]
pub struct ReleasePageQuery<'a> {
exclude_archived: Option<bool>,
ids: Option<&'a [&'a str]>,
name: Option<&'a str>,
packages: Option<&'a [&'a str]>,
updates: Option<&'a [&'a str]>,
page: u32,
rows_per_page: u32,
}
impl<'a> ReleasePageQuery<'a> {
pub fn from_query(query: &'a ReleaseQuery, page: u32) -> Self {
ReleasePageQuery {
exclude_archived: query.exclude_archived,
ids: query.ids,
name: query.name,
packages: query.packages,
updates: query.updates,
page,
rows_per_page: query.rows_per_page,
}
}
}
impl<'a> SingleRequest<ReleaseListPage, Vec<Release>> for ReleasePageQuery<'a> {
fn method(&self) -> RequestMethod {
RequestMethod::GET
}
fn path(&self) -> Result<String, QueryError> {
Ok(format!("/releases/?{}", serde_url_params::to_string(self)?))
}
fn parse(&self, string: &str) -> Result<ReleaseListPage, QueryError> {
let page: ReleaseListPage = serde_json::from_str(string)?;
Ok(page)
}
fn extract(&self, page: ReleaseListPage) -> Vec<Release> {
page.releases
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct ReleaseListPage {
releases: Vec<Release>,
page: u32,
pages: u32,
rows_per_page: u32,
total: u32,
}
impl Pagination for ReleaseListPage {
fn pages(&self) -> u32 {
self.pages
}
}
impl<'a> PaginatedRequest<ReleaseListPage, Vec<Release>> for ReleaseQuery<'a> {
fn page_request<'b>(&'b self, page: u32) -> Box<dyn SingleRequest<ReleaseListPage, Vec<Release>> + 'b> {
Box::new(ReleasePageQuery::from_query(self, page))
}
fn callback(&self, page: u32, pages: u32) {
if let Some(ref callback) = &self.callback {
callback(page, pages)
}
}
}