pimalaya_cli/
capability.rs1use std::fmt;
10
11use schemars::JsonSchema;
12use serde::Serialize;
13
14use crate::{listing::Listing, sanitize};
15
16#[derive(Clone, Debug, Serialize, JsonSchema)]
18#[serde(rename_all = "camelCase")]
19pub struct AccountCapabilityOutput {
20 pub account: String,
22 pub capabilities: Vec<AccountCapability>,
25}
26
27#[derive(Clone, Debug, Serialize, JsonSchema)]
29#[serde(rename_all = "camelCase")]
30pub struct AccountCapability {
31 pub name: String,
34 pub backend: Option<String>,
37 pub level: CapabilityLevel,
39 pub detail: Option<String>,
41}
42
43#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, JsonSchema)]
45#[serde(rename_all = "kebab-case")]
46pub enum CapabilityLevel {
47 Full,
49 Partial,
51 Server,
53 None,
55}
56
57impl fmt::Display for CapabilityLevel {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 f.write_str(match self {
60 Self::Full => "full",
61 Self::Partial => "partial",
62 Self::Server => "server",
63 Self::None => "none",
64 })
65 }
66}
67
68impl fmt::Display for AccountCapabilityOutput {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 let mut listing = Listing::new(&self.account, None);
71
72 for capability in &self.capabilities {
73 let detail = capability.detail.as_deref().unwrap_or_default();
74
75 listing.items.push([
76 sanitize::text(&capability.name).into_owned(),
77 capability.backend.clone().unwrap_or_default(),
78 capability.level.to_string(),
79 sanitize::text(detail).into_owned(),
80 ]);
81 }
82
83 write!(f, "{listing}")
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use serde_json::json;
90
91 use crate::capability::*;
92
93 #[test]
94 fn capabilities_print_one_line_each_under_the_account() {
95 let output = AccountCapabilityOutput {
96 account: String::from("work"),
97 capabilities: vec![
98 AccountCapability {
99 name: String::from("message.move"),
100 backend: Some(String::from("imap")),
101 level: CapabilityLevel::Full,
102 detail: None,
103 },
104 AccountCapability {
105 name: String::from("message.send"),
106 backend: None,
107 level: CapabilityLevel::None,
108 detail: Some(String::from("No transport")),
109 },
110 ],
111 };
112
113 let expected = "\
114Account: work
115
116message.move imap full -
117message.send - none No transport
118";
119 assert_eq!(output.to_string(), expected);
120
121 let json = serde_json::to_value(&output).unwrap();
122 let second = json!({
123 "name": "message.send",
124 "backend": null,
125 "level": "none",
126 "detail": "No transport",
127 });
128 assert_eq!(json["capabilities"][1], second);
129 }
130}