use std::io::Write;
use serde::Serialize;
use super::formatting::write_json;
use crate::types::OutputFormat;
pub fn write_result<W: Write + ?Sized>(
value: &(impl Serialize + ?Sized),
human_message: &str,
format: OutputFormat,
out: &mut W,
) {
match format {
OutputFormat::Json => write_json(value, out),
OutputFormat::Table => {
let _ = writeln!(out, "{human_message}");
}
}
}
#[derive(Debug, Serialize)]
pub enum ResourceKind {
#[serde(rename = "bug")]
Bug,
#[serde(rename = "attachment")]
Attachment,
#[serde(rename = "comment")]
Comment,
#[serde(rename = "user")]
User,
#[serde(rename = "group")]
Group,
#[serde(rename = "product")]
Product,
#[serde(rename = "component")]
Component,
#[serde(rename = "server")]
Server,
}
#[derive(Debug, Serialize)]
pub enum ActionKind {
#[serde(rename = "created")]
Created,
#[serde(rename = "updated")]
Updated,
#[serde(rename = "added")]
Added,
#[serde(rename = "removed")]
Removed,
#[serde(rename = "downloaded")]
Downloaded,
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct MembershipResult {
pub user: String,
pub group: String,
pub resource: ResourceKind,
pub action: ActionKind,
}
impl MembershipResult {
pub fn added(user: impl Into<String>, group: impl Into<String>) -> Self {
Self {
user: user.into(),
group: group.into(),
resource: ResourceKind::Group,
action: ActionKind::Added,
}
}
pub fn removed(user: impl Into<String>, group: impl Into<String>) -> Self {
Self {
user: user.into(),
group: group.into(),
resource: ResourceKind::Group,
action: ActionKind::Removed,
}
}
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct DownloadResult {
pub id: u64,
pub file: String,
pub size: usize,
pub resource: ResourceKind,
pub action: ActionKind,
}
impl DownloadResult {
pub fn new(id: u64, file: impl Into<String>, size: usize) -> Self {
Self {
id,
file: file.into(),
size,
resource: ResourceKind::Attachment,
action: ActionKind::Downloaded,
}
}
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct UploadResult {
pub id: u64,
pub bug_id: u64,
pub size: usize,
pub resource: ResourceKind,
pub action: ActionKind,
}
impl UploadResult {
pub fn new(id: u64, bug_id: u64, size: usize) -> Self {
Self {
id,
bug_id,
size,
resource: ResourceKind::Attachment,
action: ActionKind::Created,
}
}
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct TagResult {
pub comment_id: u64,
pub tags: Vec<String>,
pub resource: ResourceKind,
pub action: ActionKind,
}
impl TagResult {
pub fn updated(comment_id: u64, tags: Vec<String>) -> Self {
Self {
comment_id,
tags,
resource: ResourceKind::Comment,
action: ActionKind::Updated,
}
}
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct ConfigResult {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_default: Option<bool>,
pub config_file: String,
pub resource: ResourceKind,
pub action: ActionKind,
}
impl ConfigResult {
pub fn configured(
name: impl Into<String>,
url: impl Into<String>,
is_default: bool,
config_file: impl Into<String>,
is_update: bool,
) -> Self {
Self {
name: name.into(),
url: Some(url.into()),
is_default: Some(is_default),
config_file: config_file.into(),
resource: ResourceKind::Server,
action: if is_update {
ActionKind::Updated
} else {
ActionKind::Created
},
}
}
pub fn default_set(name: impl Into<String>, config_file: impl Into<String>) -> Self {
Self {
name: name.into(),
url: None,
is_default: None,
config_file: config_file.into(),
resource: ResourceKind::Server,
action: ActionKind::Updated,
}
}
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct SearchResult {
pub items: Vec<String>,
}
impl SearchResult {
pub fn new(items: Vec<String>) -> Self {
Self { items }
}
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct BatchResult {
pub resource: ResourceKind,
pub action: ActionKind,
pub succeeded: Vec<u64>,
pub failed: Vec<BatchFailure>,
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct BatchFailure {
pub id: u64,
pub error: String,
}
impl BatchResult {
pub fn new(succeeded: Vec<u64>, failed: Vec<BatchFailure>) -> Self {
Self {
resource: ResourceKind::Bug,
action: ActionKind::Updated,
succeeded,
failed,
}
}
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct MultiBugViewResult {
pub bugs: Vec<crate::types::Bug>,
pub failed: Vec<BugViewFailure>,
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct BugViewFailure {
pub id: String,
pub error: String,
}
#[derive(Debug, Serialize)]
#[non_exhaustive]
pub struct ActionResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub resource: ResourceKind,
pub action: ActionKind,
}
impl ActionResult {
pub fn created(id: u64, resource: ResourceKind) -> Self {
Self {
id: Some(id),
name: None,
resource,
action: ActionKind::Created,
}
}
pub fn created_named(id: u64, name: impl Into<String>, resource: ResourceKind) -> Self {
Self {
id: Some(id),
name: Some(name.into()),
resource,
action: ActionKind::Created,
}
}
pub fn updated(id: u64, resource: ResourceKind) -> Self {
Self {
id: Some(id),
name: None,
resource,
action: ActionKind::Updated,
}
}
pub fn updated_named(name: impl Into<String>, id: Option<u64>, resource: ResourceKind) -> Self {
Self {
id,
name: Some(name.into()),
resource,
action: ActionKind::Updated,
}
}
}
#[cfg(test)]
#[path = "result_types_tests.rs"]
mod tests;