diff --git a/src/formatting.rs b/src/formatting.rs new file mode 100644 index 0000000..f0c025b --- /dev/null +++ b/src/formatting.rs @@ -0,0 +1,156 @@ +// Copyright (C) 2023-2025 RabbitMQ Core Team (teamrabbitmq@gmail.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use crate::responses::{TagList, TagMap, XArguments}; +use serde_json::Map; +use std::fmt; + +impl fmt::Display for TagList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt_comma_separated_list(f, &self.0) + } +} + +#[allow(dead_code)] +pub fn fmt_list_as_json_array(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { + match xs.len() { + 0 => { + write!(f, "[]") + } + _ => { + write!(f, "[")?; + let mut xs = xs.to_owned(); + let last_element = xs.pop().unwrap(); + for elem in xs { + write!(f, "{}, ", elem)?; + } + write!(f, "{}", last_element)?; + write!(f, "]")?; + Ok(()) + } + } +} + +pub fn fmt_comma_separated_list(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { + match xs.len() { + 0 => { + write!(f, "") + } + _ => { + let mut xs = xs.to_owned(); + let last_element = xs.pop().unwrap(); + for elem in xs { + write!(f, "{}, ", elem)?; + } + write!(f, "{}", last_element)?; + Ok(()) + } + } +} + +pub fn fmt_vertical_list_with_bullets(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { + match xs.len() { + 0 => { + write!(f, "") + } + _ => { + let mut xs = xs.to_owned(); + let last_element = xs.pop().unwrap(); + for elem in xs { + writeln!(f, "* {}", elem)?; + } + write!(f, "* {}", last_element)?; + Ok(()) + } + } +} + +pub fn fmt_vertical_list_without_bullets(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { + match xs.len() { + 0 => { + write!(f, "") + } + _ => { + let mut xs = xs.to_owned(); + let last_element = xs.pop().unwrap(); + for elem in xs { + writeln!(f, "{}", elem)?; + } + write!(f, "{}", last_element)?; + Ok(()) + } + } +} + +pub fn fmt_map_as_colon_separated_pairs( + f: &mut fmt::Formatter<'_>, + xs: &Map, +) -> fmt::Result { + for (k, v) in xs.iter() { + writeln!(f, "{}: {}", k, v)?; + } + + Ok(()) +} + +pub fn display_option(opt: &Option) -> String +where + T: fmt::Display, +{ + match opt { + None => "".to_owned(), + Some(val) => format!("{}", val).to_owned(), + } +} + +pub fn display_arg_table(xs: &XArguments) -> String { + let mut s = String::new(); + for (k, v) in xs.0.iter() { + let line = format!("{}: {}\n", k, v); + s += line.as_str() + } + + s.clone() +} + +pub fn display_tag_map_option(opt: &Option) -> String { + match opt { + Some(val) => { + let mut s = String::new(); + let iter = val.0.clone().into_iter(); + for (k, v) in iter { + let line = format!("{}: {}\n", k, v); + s += line.as_str() + } + + s.clone() + } + None => "".to_owned(), + } +} + +pub fn display_tag_list_option(opt: &Option) -> String { + match opt { + Some(val) => { + let mut s = String::new(); + let iter = val.0.clone().into_iter(); + for t in iter { + let line = format!("{}\n", t); + s += line.as_str() + } + + s.clone() + } + None => "".to_owned(), + } +} diff --git a/src/lib.rs b/src/lib.rs index 2a0a142..d193c59 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,8 @@ pub mod api; pub mod blocking_api; /// Types commonly used by API requests and responses pub mod commons; +/// Formatting helpers +pub mod formatting; /// Providers password hashing utilities for user pre-seeding. pub mod password_hashing; /// Types used to issues API requests (such as `PUT`, `POST`, `DELETE`) diff --git a/src/responses.rs b/src/responses.rs index abf52d4..3b663d4 100644 --- a/src/responses.rs +++ b/src/responses.rs @@ -15,6 +15,7 @@ use core::fmt::Display; use std::{fmt, ops}; use crate::commons::{BindingDestinationType, PolicyTarget}; +use crate::formatting::*; use crate::utils::{percentage, percentage_as_text}; use serde::{ de::{MapAccess, Visitor}, @@ -28,119 +29,9 @@ use std::borrow::Cow; #[cfg(feature = "tabled")] use tabled::Tabled; -#[allow(dead_code)] -fn fmt_list_as_json_array(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { - match xs.len() { - 0 => { - write!(f, "[]") - } - _ => { - write!(f, "[")?; - let mut xs = xs.to_owned(); - let last_element = xs.pop().unwrap(); - for elem in xs { - write!(f, "{}, ", elem)?; - } - write!(f, "{}", last_element)?; - write!(f, "]")?; - Ok(()) - } - } -} - -fn fmt_comma_separated_list(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { - match xs.len() { - 0 => { - write!(f, "") - } - _ => { - let mut xs = xs.to_owned(); - let last_element = xs.pop().unwrap(); - for elem in xs { - write!(f, "{}, ", elem)?; - } - write!(f, "{}", last_element)?; - Ok(()) - } - } -} - -fn fmt_vertical_list_with_bullets(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { - match xs.len() { - 0 => { - write!(f, "") - } - _ => { - let mut xs = xs.to_owned(); - let last_element = xs.pop().unwrap(); - for elem in xs { - writeln!(f, "* {}", elem)?; - } - write!(f, "* {}", last_element)?; - Ok(()) - } - } -} - -fn fmt_vertical_list_without_bullets(f: &mut fmt::Formatter<'_>, xs: &[String]) -> fmt::Result { - match xs.len() { - 0 => { - write!(f, "") - } - _ => { - let mut xs = xs.to_owned(); - let last_element = xs.pop().unwrap(); - for elem in xs { - writeln!(f, "{}", elem)?; - } - write!(f, "{}", last_element)?; - Ok(()) - } - } -} - -fn fmt_map_as_colon_separated_pairs( - f: &mut fmt::Formatter<'_>, - xs: &Map, -) -> fmt::Result { - for (k, v) in xs.iter() { - writeln!(f, "{}: {}", k, v)?; - } - - Ok(()) -} - -#[cfg(feature = "tabled")] -fn display_option(opt: &Option) -> String -where - T: fmt::Display, -{ - match opt { - None => "".to_owned(), - Some(val) => format!("{}", val).to_owned(), - } -} - -#[cfg(feature = "tabled")] -fn display_arg_table(xs: &XArguments) -> String { - let mut s = String::new(); - for (k, v) in xs.0.iter() { - let line = format!("{}: {}\n", k, v); - s += line.as_str() - } - - s.clone() -} - #[derive(Debug, Serialize, Deserialize, Clone)] pub struct TagList(pub Vec); -impl fmt::Display for TagList { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt_comma_separated_list(f, &self.0) - } -} - #[derive(Debug, Serialize, Deserialize, Clone)] pub struct PluginList(pub Vec); @@ -1191,9 +1082,9 @@ pub struct Overview { pub product_version: String, // these two won't be available in 3.13.x - #[cfg_attr(feature = "tabled", tabled(display_with = "display_option"))] + #[cfg_attr(feature = "tabled", tabled(display_with = "display_tag_map_option"))] pub cluster_tags: Option, - #[cfg_attr(feature = "tabled", tabled(display_with = "display_option"))] + #[cfg_attr(feature = "tabled", tabled(display_with = "display_tag_map_option"))] pub node_tags: Option, pub statistics_db_event_queue: u64,