use crate::api_generator_config::{GeneratorConfig, PlaygroundConfig};
use crate::error::{Result, SklearsError};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiReference {
pub crate_name: String,
pub version: String,
pub traits: Vec<TraitInfo>,
pub types: Vec<TypeInfo>,
pub examples: Vec<CodeExample>,
pub cross_references: HashMap<String, Vec<String>>,
pub metadata: ApiMetadata,
}
impl ApiReference {
pub fn to_json(&self) -> Result<String> {
serde_json::to_string_pretty(self)
.map_err(|e| SklearsError::InvalidInput(format!("JSON serialization failed: {}", e)))
}
pub fn to_html(&self) -> Result<String> {
let mut html = String::new();
html.push_str(&format!(
"<html><head><title>API Reference - {}</title></head><body>",
self.crate_name
));
html.push_str(&format!("<h1>API Reference for {}</h1>", self.crate_name));
if !self.traits.is_empty() {
html.push_str("<h2>Traits</h2>");
for trait_info in &self.traits {
html.push_str(&format!("<h3>{}</h3>", trait_info.name));
html.push_str(&format!("<p>{}</p>", trait_info.description));
if !trait_info.methods.is_empty() {
html.push_str("<h4>Methods</h4><ul>");
for method in &trait_info.methods {
html.push_str(&format!(
"<li><code>{}</code> - {}</li>",
method.signature, method.description
));
}
html.push_str("</ul>");
}
}
}
if !self.types.is_empty() {
html.push_str("<h2>Types</h2>");
for type_info in &self.types {
html.push_str(&format!("<h3>{}</h3>", type_info.name));
html.push_str(&format!("<p>{}</p>", type_info.description));
}
}
if !self.examples.is_empty() {
html.push_str("<h2>Examples</h2>");
for example in &self.examples {
html.push_str(&format!("<h3>{}</h3>", example.title));
html.push_str(&format!("<p>{}</p>", example.description));
html.push_str(&format!(
"<pre><code class=\"{}\">{}</code></pre>",
example.language, example.code
));
}
}
html.push_str("</body></html>");
Ok(html)
}
pub fn to_markdown(&self) -> Result<String> {
let mut md = String::new();
md.push_str(&format!("# API Reference - {}\n\n", self.crate_name));
md.push_str(&format!("Version: {}\n\n", self.version));
if !self.traits.is_empty() {
md.push_str("## Traits\n\n");
for trait_info in &self.traits {
md.push_str(&format!("### {}\n\n", trait_info.name));
md.push_str(&format!("{}\n\n", trait_info.description));
if !trait_info.methods.is_empty() {
md.push_str("#### Methods\n\n");
for method in &trait_info.methods {
md.push_str(&format!(
"- `{}` - {}\n",
method.signature, method.description
));
}
md.push('\n');
}
}
}
if !self.types.is_empty() {
md.push_str("## Types\n\n");
for type_info in &self.types {
md.push_str(&format!("### {}\n\n", type_info.name));
md.push_str(&format!("{}\n\n", type_info.description));
}
}
if !self.examples.is_empty() {
md.push_str("## Examples\n\n");
for example in &self.examples {
md.push_str(&format!("### {}\n\n", example.title));
md.push_str(&format!("{}\n\n", example.description));
md.push_str(&format!(
"```{}\n{}\n```\n\n",
example.language, example.code
));
}
}
Ok(md)
}
pub fn to_interactive(&self) -> Result<String> {
let mut html = String::new();
html.push_str("<!DOCTYPE html><html><head>");
html.push_str("<title>Interactive API Reference</title>");
html.push_str(
"<script src=\"https://unpkg.com/@webassembly/wasi-sdk@0.11.0/bin/wasm-ld\"></script>",
);
html.push_str("</head><body>");
html.push_str(&format!(
"<h1>Interactive Reference - {}</h1>",
self.crate_name
));
html.push_str("<div id=\"playground\">");
html.push_str("<textarea id=\"code-editor\" rows=\"20\" cols=\"80\">");
if let Some(example) = self.examples.first() {
html.push_str(&example.code);
} else {
html.push_str(
"// Write your code here\nfn main() {\n println!(\"Hello, sklears!\");\n}",
);
}
html.push_str("</textarea>");
html.push_str("<br><button onclick=\"runCode()\">Run Code</button>");
html.push_str("<div id=\"output\"></div>");
html.push_str("</div>");
html.push_str("<script>");
html.push_str("function runCode() {");
html.push_str(" const code = document.getElementById('code-editor').value;");
html.push_str(
" document.getElementById('output').innerHTML = 'Code execution would happen here';",
);
html.push('}');
html.push_str("</script>");
html.push_str("</body></html>");
Ok(html)
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct CrateInfo {
pub name: String,
pub version: String,
pub description: String,
pub modules: Vec<String>,
pub dependencies: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiMetadata {
pub generation_time: String,
pub generator_version: String,
pub crate_version: String,
pub rust_version: String,
pub config: GeneratorConfig,
}
impl Default for ApiMetadata {
fn default() -> Self {
Self {
generation_time: chrono::Utc::now().to_string(),
generator_version: env!("CARGO_PKG_VERSION").to_string(),
crate_version: "unknown".to_string(),
rust_version: env!("CARGO_PKG_RUST_VERSION").to_string(),
config: GeneratorConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TraitInfo {
pub name: String,
pub description: String,
pub path: String,
pub generics: Vec<String>,
pub associated_types: Vec<AssociatedType>,
pub methods: Vec<MethodInfo>,
pub supertraits: Vec<String>,
pub implementations: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AssociatedType {
pub name: String,
pub description: String,
pub bounds: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MethodInfo {
pub name: String,
pub signature: String,
pub description: String,
pub parameters: Vec<ParameterInfo>,
pub return_type: String,
pub required: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ParameterInfo {
pub name: String,
pub param_type: String,
pub description: String,
pub optional: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeInfo {
pub name: String,
pub description: String,
pub path: String,
pub kind: TypeKind,
pub generics: Vec<String>,
pub fields: Vec<FieldInfo>,
pub trait_impls: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TypeKind {
Struct,
Enum,
Union,
TypeAlias,
Trait,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldInfo {
pub name: String,
pub field_type: String,
pub description: String,
pub visibility: Visibility,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Visibility {
Public,
Private,
Restricted(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodeExample {
pub title: String,
pub description: String,
pub code: String,
pub language: String,
pub runnable: bool,
pub expected_output: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionResult {
pub stdout: String,
pub stderr: String,
pub exit_code: i32,
pub execution_time: Duration,
pub memory_used: usize,
pub output: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InteractiveDocumentation {
pub api_reference: ApiReference,
pub live_examples: Vec<LiveCodeExample>,
pub searchable_index: SearchIndex,
pub interactive_tutorials: Vec<InteractiveTutorial>,
pub visualizations: Vec<ApiVisualization>,
pub playground_config: PlaygroundConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LiveCodeExample {
pub original_example: CodeExample,
pub execution_result: ExecutionResult,
pub interactive_elements: Vec<InteractiveElement>,
pub visualization: ExampleVisualization,
pub editable: bool,
pub real_time_feedback: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InteractiveElement {
pub element_type: InteractiveElementType,
pub id: String,
pub label: String,
pub action: String,
pub target: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum InteractiveElementType {
Button,
Slider,
Toggle,
Input,
Dropdown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExampleVisualization {
pub visualization_type: VisualizationType,
pub data: String,
pub interactive: bool,
pub real_time_updates: bool,
pub config: VisualizationConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VisualizationType {
FlowChart,
Graph,
Timeline,
Tree,
Network,
Chart,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VisualizationConfig {
pub width: u32,
pub height: u32,
pub theme: String,
pub animation_enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InteractiveTutorial {
pub title: String,
pub description: String,
pub steps: Vec<TutorialStep>,
pub difficulty: TutorialDifficulty,
pub estimated_time: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TutorialStep {
pub title: String,
pub content: String,
pub code_example: Option<CodeExample>,
pub interactive_elements: Vec<InteractiveElement>,
pub expected_outcome: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TutorialDifficulty {
Beginner,
Intermediate,
Advanced,
Expert,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiVisualization {
pub title: String,
pub visualization_type: VisualizationType,
pub data: ApiVisualizationData,
pub config: VisualizationConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiVisualizationData {
pub nodes: Vec<VisualizationNode>,
pub edges: Vec<VisualizationEdge>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VisualizationNode {
pub id: String,
pub label: String,
pub node_type: String,
pub properties: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VisualizationEdge {
pub source: String,
pub target: String,
pub label: String,
pub edge_type: String,
pub properties: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WasmPlayground {
pub html_template: String,
pub javascript_code: String,
pub css_styling: String,
pub rust_code: String,
pub build_instructions: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WasmBinding {
pub rust_name: String,
pub js_name: String,
pub methods: Vec<WasmMethod>,
pub examples: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WasmMethod {
pub name: String,
pub js_signature: String,
pub description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UIComponent {
pub name: String,
pub component_type: UIComponentType,
pub props: Vec<(String, String)>,
pub template: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum UIComponentType {
CodeEditor,
OutputPanel,
ApiExplorer,
ExampleGallery,
SearchBox,
NavigationMenu,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchIndex {
pub items: Vec<SearchItem>,
pub metadata: SearchMetadata,
}
impl SearchIndex {
pub fn new() -> Self {
Self {
items: Vec::new(),
metadata: SearchMetadata::default(),
}
}
pub fn add_item(&mut self, item: SearchItem) -> Result<()> {
self.items.push(item);
self.metadata.total_items += 1;
Ok(())
}
pub fn search(&self, query: &str) -> Vec<&SearchItem> {
self.items
.iter()
.filter(|item| {
item.name.to_lowercase().contains(&query.to_lowercase())
|| item
.description
.to_lowercase()
.contains(&query.to_lowercase())
|| item
.keywords
.iter()
.any(|keyword| keyword.to_lowercase().contains(&query.to_lowercase()))
})
.collect()
}
}
impl Default for SearchIndex {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchItem {
pub name: String,
pub item_type: SearchItemType,
pub description: String,
pub path: String,
pub keywords: Vec<String>,
pub relevance_score: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SearchItemType {
Trait,
Type,
Method,
Function,
Example,
Tutorial,
Documentation,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchMetadata {
pub total_items: usize,
pub created_at: String,
pub updated_at: String,
pub version: String,
}
impl Default for SearchMetadata {
fn default() -> Self {
let now = chrono::Utc::now().to_string();
Self {
total_items: 0,
created_at: now.clone(),
updated_at: now,
version: "1.0.0".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnhancedSearchIndex {
pub semantic_search: SemanticSearchEngine,
pub type_based_search: TypeSearchEngine,
pub usage_pattern_search: UsagePatternSearchEngine,
pub similarity_search: SimilaritySearchEngine,
pub auto_complete_engine: AutoCompleteEngine,
pub search_analytics: SearchAnalytics,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SemanticSearchEngine {
pub index: HashMap<String, Vec<f64>>,
pub model_config: SemanticModelConfig,
}
impl SemanticSearchEngine {
pub fn new() -> Self {
Self {
index: HashMap::new(),
model_config: SemanticModelConfig::default(),
}
}
pub fn index_trait(&mut self, trait_info: &TraitInfo) -> Result<()> {
let embedding = vec![0.0; 128]; self.index.insert(trait_info.name.clone(), embedding);
Ok(())
}
pub fn index_example(&mut self, example: &CodeExample) -> Result<()> {
let embedding = vec![0.0; 128]; self.index.insert(example.title.clone(), embedding);
Ok(())
}
}
impl Default for SemanticSearchEngine {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SemanticModelConfig {
pub model_name: String,
pub embedding_dim: usize,
pub similarity_threshold: f64,
}
impl Default for SemanticModelConfig {
fn default() -> Self {
Self {
model_name: "sentence-transformers/all-MiniLM-L6-v2".to_string(),
embedding_dim: 384,
similarity_threshold: 0.7,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeSearchEngine {
pub signatures: HashMap<String, TypeSignature>,
pub compatibility_matrix: HashMap<String, Vec<String>>,
}
impl TypeSearchEngine {
pub fn new() -> Self {
Self {
signatures: HashMap::new(),
compatibility_matrix: HashMap::new(),
}
}
pub fn index_trait_signatures(&mut self, trait_info: &TraitInfo) -> Result<()> {
for method in &trait_info.methods {
self.signatures.insert(
method.name.clone(),
TypeSignature {
signature: method.signature.clone(),
return_type: method.return_type.clone(),
parameters: method.parameters.clone(),
},
);
}
Ok(())
}
pub fn index_type_definition(&mut self, type_info: &TypeInfo) -> Result<()> {
self.compatibility_matrix
.insert(type_info.name.clone(), type_info.trait_impls.clone());
Ok(())
}
}
impl Default for TypeSearchEngine {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeSignature {
pub signature: String,
pub return_type: String,
pub parameters: Vec<ParameterInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UsagePatternSearchEngine {
pub patterns: HashMap<String, UsagePattern>,
pub frequency: HashMap<String, usize>,
}
impl UsagePatternSearchEngine {
pub fn new() -> Self {
Self {
patterns: HashMap::new(),
frequency: HashMap::new(),
}
}
pub fn index_usage_patterns(&mut self, example: &CodeExample) -> Result<()> {
let pattern = UsagePattern {
pattern_type: PatternType::FunctionCall,
code_snippet: example.code.clone(),
frequency: 1,
confidence: 0.8,
};
self.patterns.insert(example.title.clone(), pattern);
Ok(())
}
}
impl Default for UsagePatternSearchEngine {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UsagePattern {
pub pattern_type: PatternType,
pub code_snippet: String,
pub frequency: usize,
pub confidence: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PatternType {
FunctionCall,
MethodChaining,
ErrorHandling,
Initialization,
Configuration,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimilaritySearchEngine {
pub similarity_matrix: HashMap<String, HashMap<String, f64>>,
pub algorithms: Vec<SimilarityAlgorithm>,
}
impl SimilaritySearchEngine {
pub fn new() -> Self {
Self {
similarity_matrix: HashMap::new(),
algorithms: vec![SimilarityAlgorithm::Cosine, SimilarityAlgorithm::Jaccard],
}
}
pub fn index_trait_similarities(&mut self, trait_info: &TraitInfo) -> Result<()> {
let similarities = HashMap::new(); self.similarity_matrix
.insert(trait_info.name.clone(), similarities);
Ok(())
}
}
impl Default for SimilaritySearchEngine {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SimilarityAlgorithm {
Cosine,
Jaccard,
Euclidean,
Manhattan,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AutoCompleteEngine {
pub completions: HashMap<String, CompletionNode>,
pub stats: CompletionStats,
}
impl AutoCompleteEngine {
pub fn new() -> Self {
Self {
completions: HashMap::new(),
stats: CompletionStats::default(),
}
}
pub fn add_completion(&mut self, text: &str, completion_type: CompletionType) -> Result<()> {
let node = CompletionNode {
text: text.to_string(),
completion_type,
frequency: 1,
score: 1.0,
};
self.completions.insert(text.to_string(), node);
self.stats.total_completions += 1;
Ok(())
}
pub fn get_completions(&self, prefix: &str) -> Vec<&CompletionNode> {
self.completions
.values()
.filter(|node| node.text.starts_with(prefix))
.collect()
}
}
impl Default for AutoCompleteEngine {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompletionNode {
pub text: String,
pub completion_type: CompletionType,
pub frequency: usize,
pub score: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CompletionType {
Trait,
Type,
Method,
Function,
Variable,
Keyword,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompletionStats {
pub total_completions: usize,
pub popular_completions: Vec<String>,
pub accuracy: f64,
}
impl Default for CompletionStats {
fn default() -> Self {
Self {
total_completions: 0,
popular_completions: Vec::new(),
accuracy: 0.0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchAnalytics {
pub query_count: usize,
pub popular_queries: Vec<String>,
pub performance_metrics: SearchPerformanceMetrics,
}
impl SearchAnalytics {
pub fn new() -> Self {
Self {
query_count: 0,
popular_queries: Vec::new(),
performance_metrics: SearchPerformanceMetrics::default(),
}
}
}
impl Default for SearchAnalytics {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchPerformanceMetrics {
pub avg_search_time_ms: f64,
pub success_rate: f64,
pub index_size_bytes: usize,
}
impl Default for SearchPerformanceMetrics {
fn default() -> Self {
Self {
avg_search_time_ms: 0.0,
success_rate: 0.0,
index_size_bytes: 0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TutorialTemplate {
pub name: String,
pub content: String,
pub variables: HashMap<String, String>,
pub required_elements: Vec<String>,
}
#[allow(non_snake_case)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_api_reference_creation() {
let api_ref = ApiReference {
crate_name: "test-crate".to_string(),
version: "1.0.0".to_string(),
traits: Vec::new(),
types: Vec::new(),
examples: Vec::new(),
cross_references: HashMap::new(),
metadata: ApiMetadata::default(),
};
assert_eq!(api_ref.crate_name, "test-crate");
assert_eq!(api_ref.version, "1.0.0");
}
#[test]
fn test_search_index() {
let mut index = SearchIndex::new();
let item = SearchItem {
name: "TestTrait".to_string(),
item_type: SearchItemType::Trait,
description: "A test trait".to_string(),
path: "test::TestTrait".to_string(),
keywords: vec!["test".to_string(), "trait".to_string()],
relevance_score: 1.0,
};
index.add_item(item).expect("add_item should succeed");
assert_eq!(index.items.len(), 1);
assert_eq!(index.metadata.total_items, 1);
let results = index.search("test");
assert_eq!(results.len(), 1);
assert_eq!(results[0].name, "TestTrait");
}
#[test]
fn test_trait_info_default() {
let trait_info = TraitInfo::default();
assert!(trait_info.name.is_empty());
assert!(trait_info.methods.is_empty());
assert!(trait_info.associated_types.is_empty());
}
#[test]
fn test_code_example() {
let example = CodeExample {
title: "Basic Usage".to_string(),
description: "Shows basic usage".to_string(),
code: "fn main() {}".to_string(),
language: "rust".to_string(),
runnable: true,
expected_output: Some("Success".to_string()),
};
assert_eq!(example.title, "Basic Usage");
assert!(example.runnable);
}
#[test]
fn test_auto_complete_engine() {
let mut engine = AutoCompleteEngine::new();
engine
.add_completion("TestTrait", CompletionType::Trait)
.expect("expected valid value");
engine
.add_completion("TestType", CompletionType::Type)
.expect("expected valid value");
let completions = engine.get_completions("Test");
assert_eq!(completions.len(), 2);
let completions = engine.get_completions("TestT");
assert_eq!(completions.len(), 2);
let completions = engine.get_completions("TestTr");
assert_eq!(completions.len(), 1);
assert_eq!(completions[0].text, "TestTrait");
}
#[test]
fn test_serialization() {
let example = CodeExample {
title: "Test".to_string(),
description: "Test example".to_string(),
code: "println!(\"Hello\");".to_string(),
language: "rust".to_string(),
runnable: true,
expected_output: None,
};
let serialized = serde_json::to_string(&example).unwrap_or_default();
let deserialized: CodeExample =
serde_json::from_str(&serialized).expect("valid JSON operation");
assert_eq!(example.title, deserialized.title);
assert_eq!(example.code, deserialized.code);
}
}