Skip to main content

scirs2_ndimage/documentation/
types.rs

1//! Core Documentation Types and Structures
2//!
3//! This module contains all the fundamental data structures used for documentation generation,
4//! including site structure, module documentation, function documentation, tutorials, and examples.
5
6use std::collections::HashMap;
7
8/// Result type alias for documentation operations
9pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
10
11/// Main documentation site structure
12#[derive(Debug, Clone, serde::Serialize)]
13pub struct DocumentationSite {
14    /// Site title
15    pub title: String,
16    /// Site description
17    pub description: String,
18    /// Documentation version
19    pub version: String,
20    /// Base URL for the documentation
21    pub base_url: String,
22    /// Module documentation entries
23    pub modules: Vec<ModuleDoc>,
24    /// Tutorial entries
25    pub tutorials: Vec<Tutorial>,
26    /// Code examples
27    pub examples: Vec<Example>,
28}
29
30/// Documentation for a single module
31#[derive(Debug, Clone, serde::Serialize)]
32pub struct ModuleDoc {
33    /// Module name
34    pub name: String,
35    /// Module description
36    pub description: String,
37    /// Function documentation for this module
38    pub functions: Vec<FunctionDoc>,
39    /// Module-level examples
40    pub examples: Vec<String>,
41}
42
43/// Documentation for a single function
44#[derive(Debug, Clone, serde::Serialize)]
45pub struct FunctionDoc {
46    /// Function name
47    pub name: String,
48    /// Function signature
49    pub signature: String,
50    /// Function description
51    pub description: String,
52    /// Function parameters
53    pub parameters: Vec<Parameter>,
54    /// Return type and description
55    pub returns: String,
56    /// Usage examples
57    pub examples: Vec<String>,
58    /// Additional notes
59    pub notes: Vec<String>,
60}
61
62/// Function parameter documentation
63#[derive(Debug, Clone, serde::Serialize)]
64pub struct Parameter {
65    /// Parameter name
66    pub name: String,
67    /// Parameter type
68    pub param_type: String,
69    /// Parameter description
70    pub description: String,
71    /// Whether parameter is optional
72    pub optional: bool,
73}
74
75/// Tutorial content structure
76#[derive(Debug, Clone, serde::Serialize)]
77pub struct Tutorial {
78    /// Tutorial title
79    pub title: String,
80    /// Tutorial description
81    pub description: String,
82    /// Tutorial content (markdown format)
83    pub content: String,
84    /// Code examples within the tutorial
85    pub code_examples: Vec<String>,
86    /// Difficulty level (Beginner, Intermediate, Advanced)
87    pub difficulty: String,
88}
89
90/// Code example structure
91#[derive(Debug, Clone, serde::Serialize)]
92pub struct Example {
93    /// Example title
94    pub title: String,
95    /// Example description
96    pub description: String,
97    /// Example code
98    pub code: String,
99    /// Expected output (if applicable)
100    pub expected_output: Option<String>,
101    /// Example category
102    pub category: String,
103}
104
105impl DocumentationSite {
106    /// Create a new documentation site with default values
107    pub fn new() -> Self {
108        Self {
109            title: "SciRS2 NDImage Documentation".to_string(),
110            description:
111                "Comprehensive documentation for SciRS2 N-dimensional image processing library"
112                    .to_string(),
113            version: "0.1.0".to_string(),
114            base_url: "https://scirs2.github.io/ndimage".to_string(),
115            modules: Vec::new(),
116            tutorials: Vec::new(),
117            examples: Vec::new(),
118        }
119    }
120
121    /// Build comprehensive documentation by calling all builders
122    pub fn build_comprehensive_documentation(&mut self) -> Result<()> {
123        self.build_module_documentation()?;
124        self.build_tutorials()?;
125        self.build_examples()?;
126        Ok(())
127    }
128}
129
130impl Default for DocumentationSite {
131    fn default() -> Self {
132        Self::new()
133    }
134}
135
136impl ModuleDoc {
137    /// Create a new module documentation entry
138    pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
139        Self {
140            name: name.into(),
141            description: description.into(),
142            functions: Vec::new(),
143            examples: Vec::new(),
144        }
145    }
146
147    /// Add a function to this module's documentation
148    pub fn add_function(&mut self, function: FunctionDoc) {
149        self.functions.push(function);
150    }
151
152    /// Add an example to this module
153    pub fn add_example(&mut self, example: impl Into<String>) {
154        self.examples.push(example.into());
155    }
156}
157
158impl FunctionDoc {
159    /// Create a new function documentation entry
160    pub fn new(
161        name: impl Into<String>,
162        signature: impl Into<String>,
163        description: impl Into<String>,
164        returns: impl Into<String>,
165    ) -> Self {
166        Self {
167            name: name.into(),
168            signature: signature.into(),
169            description: description.into(),
170            returns: returns.into(),
171            parameters: Vec::new(),
172            examples: Vec::new(),
173            notes: Vec::new(),
174        }
175    }
176
177    /// Add a parameter to this function
178    pub fn add_parameter(&mut self, parameter: Parameter) {
179        self.parameters.push(parameter);
180    }
181
182    /// Add an example to this function
183    pub fn add_example(&mut self, example: impl Into<String>) {
184        self.examples.push(example.into());
185    }
186
187    /// Add a note to this function
188    pub fn add_note(&mut self, note: impl Into<String>) {
189        self.notes.push(note.into());
190    }
191}
192
193impl Parameter {
194    /// Create a new parameter documentation entry
195    pub fn new(
196        name: impl Into<String>,
197        param_type: impl Into<String>,
198        description: impl Into<String>,
199        optional: bool,
200    ) -> Self {
201        Self {
202            name: name.into(),
203            param_type: param_type.into(),
204            description: description.into(),
205            optional,
206        }
207    }
208
209    /// Create a required parameter
210    pub fn required(
211        name: impl Into<String>,
212        param_type: impl Into<String>,
213        description: impl Into<String>,
214    ) -> Self {
215        Self::new(name, param_type, description, false)
216    }
217
218    /// Create an optional parameter
219    pub fn optional(
220        name: impl Into<String>,
221        param_type: impl Into<String>,
222        description: impl Into<String>,
223    ) -> Self {
224        Self::new(name, param_type, description, true)
225    }
226}
227
228impl Tutorial {
229    /// Create a new tutorial
230    pub fn new(
231        title: impl Into<String>,
232        description: impl Into<String>,
233        content: impl Into<String>,
234        difficulty: impl Into<String>,
235    ) -> Self {
236        Self {
237            title: title.into(),
238            description: description.into(),
239            content: content.into(),
240            difficulty: difficulty.into(),
241            code_examples: Vec::new(),
242        }
243    }
244
245    /// Add a code example to this tutorial
246    pub fn add_code_example(&mut self, example: impl Into<String>) {
247        self.code_examples.push(example.into());
248    }
249
250    /// Create a beginner tutorial
251    pub fn beginner(
252        title: impl Into<String>,
253        description: impl Into<String>,
254        content: impl Into<String>,
255    ) -> Self {
256        Self::new(title, description, content, "Beginner")
257    }
258
259    /// Create an intermediate tutorial
260    pub fn intermediate(
261        title: impl Into<String>,
262        description: impl Into<String>,
263        content: impl Into<String>,
264    ) -> Self {
265        Self::new(title, description, content, "Intermediate")
266    }
267
268    /// Create an advanced tutorial
269    pub fn advanced(
270        title: impl Into<String>,
271        description: impl Into<String>,
272        content: impl Into<String>,
273    ) -> Self {
274        Self::new(title, description, content, "Advanced")
275    }
276}
277
278impl Example {
279    /// Create a new code example
280    pub fn new(
281        title: impl Into<String>,
282        description: impl Into<String>,
283        code: impl Into<String>,
284        category: impl Into<String>,
285    ) -> Self {
286        Self {
287            title: title.into(),
288            description: description.into(),
289            code: code.into(),
290            category: category.into(),
291            expected_output: None,
292        }
293    }
294
295    /// Create a new code example with expected output
296    pub fn with_output(
297        title: impl Into<String>,
298        description: impl Into<String>,
299        code: impl Into<String>,
300        category: impl Into<String>,
301        expected_output: impl Into<String>,
302    ) -> Self {
303        Self {
304            title: title.into(),
305            description: description.into(),
306            code: code.into(),
307            category: category.into(),
308            expected_output: Some(expected_output.into()),
309        }
310    }
311
312    /// Set the expected output for this example
313    pub fn set_expected_output(&mut self, output: impl Into<String>) {
314        self.expected_output = Some(output.into());
315    }
316}
317
318#[cfg(test)]
319mod tests {
320    use super::*;
321
322    #[test]
323    fn test_documentation_site_creation() {
324        let site = DocumentationSite::new();
325        assert_eq!(site.title, "SciRS2 NDImage Documentation");
326        assert_eq!(site.version, "0.1.0");
327        assert!(site.modules.is_empty());
328        assert!(site.tutorials.is_empty());
329        assert!(site.examples.is_empty());
330    }
331
332    #[test]
333    fn test_module_doc_creation() {
334        let mut module = ModuleDoc::new("filters", "Image filtering operations");
335        assert_eq!(module.name, "filters");
336        assert_eq!(module.description, "Image filtering operations");
337        assert!(module.functions.is_empty());
338
339        module.add_example("Basic filtering example");
340        assert_eq!(module.examples.len(), 1);
341    }
342
343    #[test]
344    fn test_function_doc_creation() {
345        let mut func = FunctionDoc::new(
346            "gaussian_filter",
347            "pub fn gaussian_filter<T>(input: &ArrayD<T>, sigma: f64) -> ArrayD<T>",
348            "Apply Gaussian filter to n-dimensional array",
349            "ArrayD<T> - Filtered array",
350        );
351
352        let param = Parameter::required("input", "&ArrayD<T>", "Input n-dimensional array");
353        func.add_parameter(param);
354        func.add_note("Uses separable convolution for efficiency");
355
356        assert_eq!(func.name, "gaussian_filter");
357        assert_eq!(func.parameters.len(), 1);
358        assert_eq!(func.notes.len(), 1);
359    }
360
361    #[test]
362    fn test_parameter_creation() {
363        let required_param = Parameter::required("input", "&ArrayD<T>", "Input array");
364        assert!(!required_param.optional);
365
366        let optional_param = Parameter::optional("sigma", "f64", "Standard deviation");
367        assert!(optional_param.optional);
368    }
369
370    #[test]
371    fn test_tutorial_creation() {
372        let tutorial = Tutorial::beginner(
373            "Getting Started",
374            "Introduction to image processing",
375            "# Getting Started\n\nThis tutorial covers basic operations...",
376        );
377
378        assert_eq!(tutorial.title, "Getting Started");
379        assert_eq!(tutorial.difficulty, "Beginner");
380        assert!(tutorial.code_examples.is_empty());
381    }
382
383    #[test]
384    fn test_example_creation() {
385        let example = Example::new(
386            "Basic Filtering",
387            "Simple Gaussian filter example",
388            "let filtered = gaussian_filter(&image, 2.0);",
389            "filters",
390        );
391
392        assert_eq!(example.title, "Basic Filtering");
393        assert_eq!(example.category, "filters");
394        assert!(example.expected_output.is_none());
395
396        let example_with_output = Example::with_output(
397            "Math Example",
398            "Simple math operation",
399            "2 + 2",
400            "math",
401            "4",
402        );
403
404        assert!(example_with_output.expected_output.is_some());
405        assert_eq!(
406            example_with_output
407                .expected_output
408                .expect("Operation failed"),
409            "4"
410        );
411    }
412}