use std::collections::HashMap;
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[derive(Debug, Clone, serde::Serialize)]
pub struct DocumentationSite {
pub title: String,
pub description: String,
pub version: String,
pub base_url: String,
pub modules: Vec<ModuleDoc>,
pub tutorials: Vec<Tutorial>,
pub examples: Vec<Example>,
}
#[derive(Debug, Clone)]
pub struct ModuleDoc {
pub name: String,
pub description: String,
pub functions: Vec<FunctionDoc>,
pub examples: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct FunctionDoc {
pub name: String,
pub signature: String,
pub description: String,
pub parameters: Vec<Parameter>,
pub returns: String,
pub examples: Vec<String>,
pub notes: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct Parameter {
pub name: String,
pub param_type: String,
pub description: String,
pub optional: bool,
}
#[derive(Debug, Clone)]
pub struct Tutorial {
pub title: String,
pub description: String,
pub content: String,
pub code_examples: Vec<String>,
pub difficulty: String,
}
#[derive(Debug, Clone)]
pub struct Example {
pub title: String,
pub description: String,
pub code: String,
pub expected_output: Option<String>,
pub category: String,
}
impl DocumentationSite {
pub fn new() -> Self {
Self {
title: "SciRS2 NDImage Documentation".to_string(),
description:
"Comprehensive documentation for SciRS2 N-dimensional image processing library"
.to_string(),
version: "0.1.0".to_string(),
base_url: "https://scirs2.github.io/ndimage".to_string(),
modules: Vec::new(),
tutorials: Vec::new(),
examples: Vec::new(),
}
}
pub fn build_comprehensive_documentation(&mut self) -> Result<()> {
self.build_module_documentation()?;
self.build_tutorials()?;
self.build_examples()?;
Ok(())
}
}
impl Default for DocumentationSite {
fn default() -> Self {
Self::new()
}
}
impl ModuleDoc {
pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
Self {
name: name.into(),
description: description.into(),
functions: Vec::new(),
examples: Vec::new(),
}
}
pub fn add_function(&mut self, function: FunctionDoc) {
self.functions.push(function);
}
pub fn add_example(&mut self, example: impl Into<String>) {
self.examples.push(example.into());
}
}
impl FunctionDoc {
pub fn new(
name: impl Into<String>,
signature: impl Into<String>,
description: impl Into<String>,
returns: impl Into<String>,
) -> Self {
Self {
name: name.into(),
signature: signature.into(),
description: description.into(),
returns: returns.into(),
parameters: Vec::new(),
examples: Vec::new(),
notes: Vec::new(),
}
}
pub fn add_parameter(&mut self, parameter: Parameter) {
self.parameters.push(parameter);
}
pub fn add_example(&mut self, example: impl Into<String>) {
self.examples.push(example.into());
}
pub fn add_note(&mut self, note: impl Into<String>) {
self.notes.push(note.into());
}
}
impl Parameter {
pub fn new(
name: impl Into<String>,
param_type: impl Into<String>,
description: impl Into<String>,
optional: bool,
) -> Self {
Self {
name: name.into(),
param_type: param_type.into(),
description: description.into(),
optional,
}
}
pub fn required(
name: impl Into<String>,
param_type: impl Into<String>,
description: impl Into<String>,
) -> Self {
Self::new(name, param_type, description, false)
}
pub fn optional(
name: impl Into<String>,
param_type: impl Into<String>,
description: impl Into<String>,
) -> Self {
Self::new(name, param_type, description, true)
}
}
impl Tutorial {
pub fn new(
title: impl Into<String>,
description: impl Into<String>,
content: impl Into<String>,
difficulty: impl Into<String>,
) -> Self {
Self {
title: title.into(),
description: description.into(),
content: content.into(),
difficulty: difficulty.into(),
code_examples: Vec::new(),
}
}
pub fn add_code_example(&mut self, example: impl Into<String>) {
self.code_examples.push(example.into());
}
pub fn beginner(
title: impl Into<String>,
description: impl Into<String>,
content: impl Into<String>,
) -> Self {
Self::new(title, description, content, "Beginner")
}
pub fn intermediate(
title: impl Into<String>,
description: impl Into<String>,
content: impl Into<String>,
) -> Self {
Self::new(title, description, content, "Intermediate")
}
pub fn advanced(
title: impl Into<String>,
description: impl Into<String>,
content: impl Into<String>,
) -> Self {
Self::new(title, description, content, "Advanced")
}
}
impl Example {
pub fn new(
title: impl Into<String>,
description: impl Into<String>,
code: impl Into<String>,
category: impl Into<String>,
) -> Self {
Self {
title: title.into(),
description: description.into(),
code: code.into(),
category: category.into(),
expected_output: None,
}
}
pub fn with_output(
title: impl Into<String>,
description: impl Into<String>,
code: impl Into<String>,
category: impl Into<String>,
expected_output: impl Into<String>,
) -> Self {
Self {
title: title.into(),
description: description.into(),
code: code.into(),
category: category.into(),
expected_output: Some(expected_output.into()),
}
}
pub fn set_expected_output(&mut self, output: impl Into<String>) {
self.expected_output = Some(output.into());
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_documentation_site_creation() {
let site = DocumentationSite::new();
assert_eq!(site.title, "SciRS2 NDImage Documentation");
assert_eq!(site.version, "0.1.0");
assert!(site.modules.is_empty());
assert!(site.tutorials.is_empty());
assert!(site.examples.is_empty());
}
#[test]
fn test_module_doc_creation() {
let mut module = ModuleDoc::new("filters", "Image filtering operations");
assert_eq!(module.name, "filters");
assert_eq!(module.description, "Image filtering operations");
assert!(module.functions.is_empty());
module.add_example("Basic filtering example");
assert_eq!(module.examples.len(), 1);
}
#[test]
fn test_function_doc_creation() {
let mut func = FunctionDoc::new(
"gaussian_filter",
"pub fn gaussian_filter<T>(input: &ArrayD<T>, sigma: f64) -> ArrayD<T>",
"Apply Gaussian filter to n-dimensional array",
"ArrayD<T> - Filtered array",
);
let param = Parameter::required("input", "&ArrayD<T>", "Input n-dimensional array");
func.add_parameter(param);
func.add_note("Uses separable convolution for efficiency");
assert_eq!(func.name, "gaussian_filter");
assert_eq!(func.parameters.len(), 1);
assert_eq!(func.notes.len(), 1);
}
#[test]
fn test_parameter_creation() {
let required_param = Parameter::required("input", "&ArrayD<T>", "Input array");
assert!(!required_param.optional);
let optional_param = Parameter::optional("sigma", "f64", "Standard deviation");
assert!(optional_param.optional);
}
#[test]
fn test_tutorial_creation() {
let tutorial = Tutorial::beginner(
"Getting Started",
"Introduction to image processing",
"# Getting Started\n\nThis tutorial covers basic operations...",
);
assert_eq!(tutorial.title, "Getting Started");
assert_eq!(tutorial.difficulty, "Beginner");
assert!(tutorial.code_examples.is_empty());
}
#[test]
fn test_example_creation() {
let example = Example::new(
"Basic Filtering",
"Simple Gaussian filter example",
"let filtered = gaussian_filter(&image, 2.0);",
"filters",
);
assert_eq!(example.title, "Basic Filtering");
assert_eq!(example.category, "filters");
assert!(example.expected_output.is_none());
let example_with_output = Example::with_output(
"Math Example",
"Simple math operation",
"2 + 2",
"math",
"4",
);
assert!(example_with_output.expected_output.is_some());
assert_eq!(example_with_output.expected_output.expect("Operation failed"), "4");
}
}