1use std::collections::HashMap;
7
8pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
10
11#[derive(Debug, Clone, serde::Serialize)]
13pub struct DocumentationSite {
14 pub title: String,
16 pub description: String,
18 pub version: String,
20 pub base_url: String,
22 pub modules: Vec<ModuleDoc>,
24 pub tutorials: Vec<Tutorial>,
26 pub examples: Vec<Example>,
28}
29
30#[derive(Debug, Clone, serde::Serialize)]
32pub struct ModuleDoc {
33 pub name: String,
35 pub description: String,
37 pub functions: Vec<FunctionDoc>,
39 pub examples: Vec<String>,
41}
42
43#[derive(Debug, Clone, serde::Serialize)]
45pub struct FunctionDoc {
46 pub name: String,
48 pub signature: String,
50 pub description: String,
52 pub parameters: Vec<Parameter>,
54 pub returns: String,
56 pub examples: Vec<String>,
58 pub notes: Vec<String>,
60}
61
62#[derive(Debug, Clone, serde::Serialize)]
64pub struct Parameter {
65 pub name: String,
67 pub param_type: String,
69 pub description: String,
71 pub optional: bool,
73}
74
75#[derive(Debug, Clone, serde::Serialize)]
77pub struct Tutorial {
78 pub title: String,
80 pub description: String,
82 pub content: String,
84 pub code_examples: Vec<String>,
86 pub difficulty: String,
88}
89
90#[derive(Debug, Clone, serde::Serialize)]
92pub struct Example {
93 pub title: String,
95 pub description: String,
97 pub code: String,
99 pub expected_output: Option<String>,
101 pub category: String,
103}
104
105impl DocumentationSite {
106 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 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 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 pub fn add_function(&mut self, function: FunctionDoc) {
149 self.functions.push(function);
150 }
151
152 pub fn add_example(&mut self, example: impl Into<String>) {
154 self.examples.push(example.into());
155 }
156}
157
158impl FunctionDoc {
159 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 pub fn add_parameter(&mut self, parameter: Parameter) {
179 self.parameters.push(parameter);
180 }
181
182 pub fn add_example(&mut self, example: impl Into<String>) {
184 self.examples.push(example.into());
185 }
186
187 pub fn add_note(&mut self, note: impl Into<String>) {
189 self.notes.push(note.into());
190 }
191}
192
193impl Parameter {
194 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 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 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 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 pub fn add_code_example(&mut self, example: impl Into<String>) {
247 self.code_examples.push(example.into());
248 }
249
250 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 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 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 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 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 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}