Skip to main content

oxihuman_export/
swagger_export.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Swagger 2.0 spec stub export.
6
7/// Swagger 2.0 document info.
8#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct SwaggerInfo {
11    pub title: String,
12    pub version: String,
13    pub description: String,
14}
15
16/// A Swagger path operation.
17#[allow(dead_code)]
18#[derive(Debug, Clone)]
19pub struct SwaggerOperation {
20    pub path: String,
21    pub method: String,
22    pub summary: String,
23    pub tags: Vec<String>,
24}
25
26/// A Swagger 2.0 document.
27#[allow(dead_code)]
28#[derive(Debug, Clone)]
29pub struct SwaggerDoc {
30    pub info: SwaggerInfo,
31    pub host: String,
32    pub base_path: String,
33    pub operations: Vec<SwaggerOperation>,
34}
35
36/// Create a new Swagger 2.0 document.
37#[allow(dead_code)]
38pub fn new_swagger_doc(title: &str, version: &str, host: &str) -> SwaggerDoc {
39    SwaggerDoc {
40        info: SwaggerInfo {
41            title: title.to_string(),
42            version: version.to_string(),
43            description: String::new(),
44        },
45        host: host.to_string(),
46        base_path: "/".to_string(),
47        operations: Vec::new(),
48    }
49}
50
51/// Add an operation to the swagger doc.
52#[allow(dead_code)]
53pub fn add_operation(doc: &mut SwaggerDoc, path: &str, method: &str, summary: &str) {
54    doc.operations.push(SwaggerOperation {
55        path: path.to_string(),
56        method: method.to_string(),
57        summary: summary.to_string(),
58        tags: Vec::new(),
59    });
60}
61
62/// Add a tag to the last operation.
63#[allow(dead_code)]
64pub fn add_tag(doc: &mut SwaggerDoc, tag: &str) {
65    if let Some(op) = doc.operations.last_mut() {
66        op.tags.push(tag.to_string());
67    }
68}
69
70/// Export to JSON text (Swagger 2.0 format).
71#[allow(dead_code)]
72pub fn export_swagger_json(doc: &SwaggerDoc) -> String {
73    let mut paths = String::new();
74    for (i, op) in doc.operations.iter().enumerate() {
75        let tags: Vec<String> = op.tags.iter().map(|t| format!("\"{}\"", t)).collect();
76        let entry = format!(
77            r#""{}":{{"{}": {{"summary":"{}","tags":[{}]}}}}"#,
78            op.path,
79            op.method,
80            op.summary,
81            tags.join(",")
82        );
83        if i > 0 {
84            paths.push(',');
85        }
86        paths.push_str(&entry);
87    }
88    format!(
89        r#"{{"swagger":"2.0","info":{{"title":"{}","version":"{}"}},"host":"{}","basePath":"{}","paths":{{{}}}}}"#,
90        doc.info.title, doc.info.version, doc.host, doc.base_path, paths
91    )
92}
93
94/// Operation count.
95#[allow(dead_code)]
96pub fn operation_count(doc: &SwaggerDoc) -> usize {
97    doc.operations.len()
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn new_doc_title() {
106        let doc = new_swagger_doc("My API", "1.0", "api.example.com");
107        assert_eq!(doc.info.title, "My API");
108    }
109
110    #[test]
111    fn new_doc_host() {
112        let doc = new_swagger_doc("API", "1.0", "localhost:8080");
113        assert_eq!(doc.host, "localhost:8080");
114    }
115
116    #[test]
117    fn add_operation_count() {
118        let mut doc = new_swagger_doc("API", "1.0", "host");
119        add_operation(&mut doc, "/pets", "get", "List pets");
120        assert_eq!(operation_count(&doc), 1);
121    }
122
123    #[test]
124    fn export_contains_swagger_version() {
125        let doc = new_swagger_doc("API", "1.0", "host");
126        let s = export_swagger_json(&doc);
127        assert!(s.contains("\"2.0\""));
128    }
129
130    #[test]
131    fn export_contains_title() {
132        let doc = new_swagger_doc("PetStore", "1.0", "host");
133        let s = export_swagger_json(&doc);
134        assert!(s.contains("PetStore"));
135    }
136
137    #[test]
138    fn export_contains_path() {
139        let mut doc = new_swagger_doc("API", "1.0", "host");
140        add_operation(&mut doc, "/pets", "get", "List");
141        let s = export_swagger_json(&doc);
142        assert!(s.contains("/pets"));
143    }
144
145    #[test]
146    fn add_tag_stored() {
147        let mut doc = new_swagger_doc("API", "1.0", "host");
148        add_operation(&mut doc, "/pets", "get", "List");
149        add_tag(&mut doc, "pets");
150        assert_eq!(doc.operations[0].tags.len(), 1);
151    }
152
153    #[test]
154    fn tag_in_export() {
155        let mut doc = new_swagger_doc("API", "1.0", "host");
156        add_operation(&mut doc, "/pets", "get", "List");
157        add_tag(&mut doc, "pets");
158        let s = export_swagger_json(&doc);
159        assert!(s.contains("pets"));
160    }
161
162    #[test]
163    fn add_tag_no_operations_safe() {
164        let mut doc = new_swagger_doc("API", "1.0", "host");
165        add_tag(&mut doc, "safe");
166        assert_eq!(operation_count(&doc), 0);
167    }
168
169    #[test]
170    fn base_path_default() {
171        let doc = new_swagger_doc("API", "1.0", "host");
172        assert_eq!(doc.base_path, "/");
173    }
174}