salvo_oapi/openapi/
tag.rs1use std::cmp::Ordering;
5
6use serde::{Deserialize, Serialize};
7
8use super::external_docs::ExternalDocs;
9use crate::PropMap;
10
11#[non_exhaustive]
17#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
18#[serde(rename_all = "camelCase")]
19pub struct Tag {
20 pub name: String,
22
23 #[serde(skip_serializing_if = "Option::is_none")]
25 pub description: Option<String>,
26
27 #[serde(skip_serializing_if = "Option::is_none")]
29 pub external_docs: Option<ExternalDocs>,
30
31 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
33 pub extensions: PropMap<String, serde_json::Value>,
34}
35impl Ord for Tag {
36 fn cmp(&self, other: &Self) -> Ordering {
37 self.name.cmp(&other.name)
38 }
39}
40impl PartialOrd for Tag {
41 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
42 Some(self.cmp(other))
43 }
44}
45impl From<String> for Tag {
46 fn from(name: String) -> Self {
47 Self::new(name)
48 }
49}
50impl From<&String> for Tag {
51 fn from(name: &String) -> Self {
52 Self::new(name)
53 }
54}
55impl<'a> From<&'a str> for Tag {
56 fn from(name: &'a str) -> Self {
57 Self::new(name.to_owned())
58 }
59}
60
61impl Tag {
62 #[must_use]
64 pub fn new(name: impl Into<String>) -> Self {
65 Self {
66 name: name.into(),
67 ..Default::default()
68 }
69 }
70 #[must_use]
72 pub fn name(mut self, name: impl Into<String>) -> Self {
73 self.name = name.into();
74 self
75 }
76
77 #[must_use]
79 pub fn description(mut self, description: impl Into<String>) -> Self {
80 self.description = Some(description.into());
81 self
82 }
83
84 #[must_use]
86 pub fn external_docs(mut self, external_docs: ExternalDocs) -> Self {
87 self.external_docs = Some(external_docs);
88 self
89 }
90
91 #[must_use]
93 pub fn add_extension<K: Into<String>>(mut self, key: K, value: serde_json::Value) -> Self {
94 self.extensions.insert(key.into(), value);
95 self
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::ExternalDocs;
102 use super::Tag;
103
104 #[test]
105 fn tag_new() {
106 let tag = Tag::new("tag name");
107 assert_eq!(tag.name, "tag name");
108 assert!(tag.description.is_none());
109 assert!(tag.external_docs.is_none());
110 assert!(tag.extensions.is_empty());
111
112 let tag = tag.name("new tag name");
113 assert_eq!(tag.name, "new tag name");
114
115 let tag = tag.description("description");
116 assert!(tag.description.is_some());
117
118 let tag = tag.external_docs(ExternalDocs::new(""));
119 assert!(tag.external_docs.is_some());
120 }
121
122 #[test]
123 fn from_string() {
124 let name = "tag name".to_owned();
125 let tag = Tag::from(name);
126 assert_eq!(tag.name, "tag name".to_owned());
127 }
128
129 #[test]
130 fn from_string_ref() {
131 let name = "tag name".to_owned();
132 let tag = Tag::from(&name);
133 assert_eq!(tag.name, "tag name".to_owned());
134 }
135
136 #[test]
137 fn from_str() {
138 let name = "tag name";
139 let tag = Tag::from(name);
140 assert_eq!(tag.name, "tag name");
141 }
142
143 #[test]
144 fn cmp() {
145 let tag1 = Tag::new("a");
146 let tag2 = Tag::new("b");
147
148 assert!(tag1 < tag2);
149 }
150}