use std::fmt::{Debug, Formatter};
use serde::{Deserialize, Serialize};
use crate::client::DEFAULT_ROWS;
use crate::data::{Build, FedoraRelease};
use crate::error::QueryError;
use crate::request::{PaginatedRequest, Pagination, RequestMethod, SingleRequest};
#[derive(Debug)]
pub struct BuildNVRQuery<'a> {
nvr: &'a str,
}
impl<'a> BuildNVRQuery<'a> {
pub fn new(nvr: &'a str) -> Self {
BuildNVRQuery { nvr }
}
}
impl<'a> SingleRequest<Build, Build> for BuildNVRQuery<'a> {
fn method(&self) -> RequestMethod {
RequestMethod::GET
}
fn path(&self) -> Result<String, QueryError> {
Ok(format!("/builds/{}", self.nvr))
}
fn parse(&self, string: &str) -> Result<Build, QueryError> {
let build: Build = serde_json::from_str(string)?;
Ok(build)
}
fn extract(&self, page: Build) -> Build {
page
}
}
#[derive(Default)]
pub struct BuildQuery<'a> {
nvr: Option<&'a str>,
packages: Option<&'a [&'a str]>,
releases: Option<&'a [FedoraRelease]>,
updates: Option<&'a [&'a str]>,
rows_per_page: u32,
callback: Option<Box<dyn Fn(u32, u32) + 'a>>,
}
impl<'a> Debug for BuildQuery<'a> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_struct("BuildQuery")
.field("nvr", &self.nvr)
.field("packages", &self.packages)
.field("releases", &self.releases)
.field("updates", &self.updates)
.field("rows_per_page", &self.rows_per_page)
.field("callback", &"(function pointer)")
.finish()
}
}
impl<'a> BuildQuery<'a> {
pub fn new() -> Self {
BuildQuery {
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 nvr(mut self, nvr: &'a str) -> Self {
self.nvr = Some(nvr);
self
}
#[must_use]
pub fn packages(mut self, packages: &'a [&'a str]) -> Self {
self.packages = Some(packages);
self
}
#[must_use]
pub fn releases(mut self, releases: &'a [FedoraRelease]) -> Self {
self.releases = Some(releases);
self
}
#[must_use]
pub fn updates(mut self, updates: &'a [&'a str]) -> Self {
self.updates = Some(updates);
self
}
}
#[derive(Debug, Serialize)]
pub struct BuildPageQuery<'a> {
nvr: Option<&'a str>,
packages: Option<&'a [&'a str]>,
releases: Option<&'a [FedoraRelease]>,
updates: Option<&'a [&'a str]>,
page: u32,
rows_per_page: u32,
}
impl<'a> BuildPageQuery<'a> {
pub fn from_query(query: &'a BuildQuery, page: u32) -> Self {
BuildPageQuery {
nvr: query.nvr,
packages: query.packages,
releases: query.releases,
updates: query.updates,
page,
rows_per_page: query.rows_per_page,
}
}
}
impl<'a> SingleRequest<BuildListPage, Vec<Build>> for BuildPageQuery<'a> {
fn method(&self) -> RequestMethod {
RequestMethod::GET
}
fn path(&self) -> Result<String, QueryError> {
Ok(format!("/builds/?{}", serde_url_params::to_string(self)?))
}
fn parse(&self, string: &str) -> Result<BuildListPage, QueryError> {
let page: BuildListPage = serde_json::from_str(string)?;
Ok(page)
}
fn extract(&self, page: BuildListPage) -> Vec<Build> {
page.builds
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
pub struct BuildListPage {
builds: Vec<Build>,
page: u32,
pages: u32,
rows_per_page: u32,
total: u32,
}
impl Pagination for BuildListPage {
fn pages(&self) -> u32 {
self.pages
}
}
impl<'a> PaginatedRequest<BuildListPage, Vec<Build>> for BuildQuery<'a> {
fn page_request<'b>(&'b self, page: u32) -> Box<dyn SingleRequest<BuildListPage, Vec<Build>> + 'b> {
Box::new(BuildPageQuery::from_query(self, page))
}
fn callback(&self, page: u32, pages: u32) {
if let Some(ref callback) = &self.callback {
callback(page, pages)
}
}
}