1use crate::api_generator_config::{GeneratorConfig, PlaygroundConfig};
8use crate::error::{Result, SklearsError};
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::time::Duration;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct ApiReference {
20 pub crate_name: String,
22 pub version: String,
24 pub traits: Vec<TraitInfo>,
26 pub types: Vec<TypeInfo>,
28 pub examples: Vec<CodeExample>,
30 pub cross_references: HashMap<String, Vec<String>>,
32 pub metadata: ApiMetadata,
34}
35
36impl ApiReference {
37 pub fn to_json(&self) -> Result<String> {
39 serde_json::to_string_pretty(self)
40 .map_err(|e| SklearsError::InvalidInput(format!("JSON serialization failed: {}", e)))
41 }
42
43 pub fn to_html(&self) -> Result<String> {
45 let mut html = String::new();
46 html.push_str(&format!(
47 "<html><head><title>API Reference - {}</title></head><body>",
48 self.crate_name
49 ));
50 html.push_str(&format!("<h1>API Reference for {}</h1>", self.crate_name));
51
52 if !self.traits.is_empty() {
54 html.push_str("<h2>Traits</h2>");
55 for trait_info in &self.traits {
56 html.push_str(&format!("<h3>{}</h3>", trait_info.name));
57 html.push_str(&format!("<p>{}</p>", trait_info.description));
58
59 if !trait_info.methods.is_empty() {
60 html.push_str("<h4>Methods</h4><ul>");
61 for method in &trait_info.methods {
62 html.push_str(&format!(
63 "<li><code>{}</code> - {}</li>",
64 method.signature, method.description
65 ));
66 }
67 html.push_str("</ul>");
68 }
69 }
70 }
71
72 if !self.types.is_empty() {
74 html.push_str("<h2>Types</h2>");
75 for type_info in &self.types {
76 html.push_str(&format!("<h3>{}</h3>", type_info.name));
77 html.push_str(&format!("<p>{}</p>", type_info.description));
78 }
79 }
80
81 if !self.examples.is_empty() {
83 html.push_str("<h2>Examples</h2>");
84 for example in &self.examples {
85 html.push_str(&format!("<h3>{}</h3>", example.title));
86 html.push_str(&format!("<p>{}</p>", example.description));
87 html.push_str(&format!(
88 "<pre><code class=\"{}\">{}</code></pre>",
89 example.language, example.code
90 ));
91 }
92 }
93
94 html.push_str("</body></html>");
95 Ok(html)
96 }
97
98 pub fn to_markdown(&self) -> Result<String> {
100 let mut md = String::new();
101 md.push_str(&format!("# API Reference - {}\n\n", self.crate_name));
102 md.push_str(&format!("Version: {}\n\n", self.version));
103
104 if !self.traits.is_empty() {
106 md.push_str("## Traits\n\n");
107 for trait_info in &self.traits {
108 md.push_str(&format!("### {}\n\n", trait_info.name));
109 md.push_str(&format!("{}\n\n", trait_info.description));
110
111 if !trait_info.methods.is_empty() {
112 md.push_str("#### Methods\n\n");
113 for method in &trait_info.methods {
114 md.push_str(&format!(
115 "- `{}` - {}\n",
116 method.signature, method.description
117 ));
118 }
119 md.push('\n');
120 }
121 }
122 }
123
124 if !self.types.is_empty() {
126 md.push_str("## Types\n\n");
127 for type_info in &self.types {
128 md.push_str(&format!("### {}\n\n", type_info.name));
129 md.push_str(&format!("{}\n\n", type_info.description));
130 }
131 }
132
133 if !self.examples.is_empty() {
135 md.push_str("## Examples\n\n");
136 for example in &self.examples {
137 md.push_str(&format!("### {}\n\n", example.title));
138 md.push_str(&format!("{}\n\n", example.description));
139 md.push_str(&format!(
140 "```{}\n{}\n```\n\n",
141 example.language, example.code
142 ));
143 }
144 }
145
146 Ok(md)
147 }
148
149 pub fn to_interactive(&self) -> Result<String> {
151 let mut html = String::new();
152 html.push_str("<!DOCTYPE html><html><head>");
153 html.push_str("<title>Interactive API Reference</title>");
154 html.push_str(
155 "<script src=\"https://unpkg.com/@webassembly/wasi-sdk@0.11.0/bin/wasm-ld\"></script>",
156 );
157 html.push_str("</head><body>");
158 html.push_str(&format!(
159 "<h1>Interactive Reference - {}</h1>",
160 self.crate_name
161 ));
162 html.push_str("<div id=\"playground\">");
163 html.push_str("<textarea id=\"code-editor\" rows=\"20\" cols=\"80\">");
164
165 if let Some(example) = self.examples.first() {
167 html.push_str(&example.code);
168 } else {
169 html.push_str(
170 "// Write your code here\nfn main() {\n println!(\"Hello, sklears!\");\n}",
171 );
172 }
173
174 html.push_str("</textarea>");
175 html.push_str("<br><button onclick=\"runCode()\">Run Code</button>");
176 html.push_str("<div id=\"output\"></div>");
177 html.push_str("</div>");
178 html.push_str("<script>");
179 html.push_str("function runCode() {");
180 html.push_str(" const code = document.getElementById('code-editor').value;");
181 html.push_str(
182 " document.getElementById('output').innerHTML = 'Code execution would happen here';",
183 );
184 html.push('}');
185 html.push_str("</script>");
186 html.push_str("</body></html>");
187
188 Ok(html)
189 }
190}
191
192#[derive(Debug, Clone)]
194#[allow(dead_code)]
195pub struct CrateInfo {
196 pub name: String,
197 pub version: String,
198 pub description: String,
199 pub modules: Vec<String>,
200 pub dependencies: Vec<String>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct ApiMetadata {
206 pub generation_time: String,
208 pub generator_version: String,
210 pub crate_version: String,
212 pub rust_version: String,
214 pub config: GeneratorConfig,
216}
217
218impl Default for ApiMetadata {
219 fn default() -> Self {
220 Self {
221 generation_time: chrono::Utc::now().to_string(),
222 generator_version: env!("CARGO_PKG_VERSION").to_string(),
223 crate_version: "unknown".to_string(),
224 rust_version: env!("CARGO_PKG_RUST_VERSION").to_string(),
225 config: GeneratorConfig::default(),
226 }
227 }
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize, Default)]
236pub struct TraitInfo {
237 pub name: String,
239 pub description: String,
241 pub path: String,
243 pub generics: Vec<String>,
245 pub associated_types: Vec<AssociatedType>,
247 pub methods: Vec<MethodInfo>,
249 pub supertraits: Vec<String>,
251 pub implementations: Vec<String>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize, Default)]
257pub struct AssociatedType {
258 pub name: String,
260 pub description: String,
262 pub bounds: Vec<String>,
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize, Default)]
268pub struct MethodInfo {
269 pub name: String,
271 pub signature: String,
273 pub description: String,
275 pub parameters: Vec<ParameterInfo>,
277 pub return_type: String,
279 pub required: bool,
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize, Default)]
285pub struct ParameterInfo {
286 pub name: String,
288 pub param_type: String,
290 pub description: String,
292 pub optional: bool,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
302pub struct TypeInfo {
303 pub name: String,
305 pub description: String,
307 pub path: String,
309 pub kind: TypeKind,
311 pub generics: Vec<String>,
313 pub fields: Vec<FieldInfo>,
315 pub trait_impls: Vec<String>,
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
321pub enum TypeKind {
322 Struct,
323 Enum,
324 Union,
325 TypeAlias,
326 Trait,
327}
328
329#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct FieldInfo {
332 pub name: String,
334 pub field_type: String,
336 pub description: String,
338 pub visibility: Visibility,
340}
341
342#[derive(Debug, Clone, Serialize, Deserialize)]
344pub enum Visibility {
345 Public,
346 Private,
347 Restricted(String),
348}
349
350impl std::fmt::Display for Visibility {
351 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
352 match self {
353 Visibility::Public => write!(f, "public"),
354 Visibility::Private => write!(f, "private"),
355 Visibility::Restricted(path) => write!(f, "restricted({path})"),
356 }
357 }
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
366pub struct CodeExample {
367 pub title: String,
369 pub description: String,
371 pub code: String,
373 pub language: String,
375 pub runnable: bool,
377 pub expected_output: Option<String>,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
383pub struct ExecutionResult {
384 pub stdout: String,
386 pub stderr: String,
388 pub exit_code: i32,
390 pub execution_time: Duration,
392 pub memory_used: usize,
394 pub output: String,
396}
397
398#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct InteractiveDocumentation {
405 pub api_reference: ApiReference,
407 pub live_examples: Vec<LiveCodeExample>,
409 pub searchable_index: SearchIndex,
411 pub interactive_tutorials: Vec<InteractiveTutorial>,
413 pub visualizations: Vec<ApiVisualization>,
415 pub playground_config: PlaygroundConfig,
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize)]
421pub struct LiveCodeExample {
422 pub original_example: CodeExample,
424 pub execution_result: ExecutionResult,
426 pub interactive_elements: Vec<InteractiveElement>,
428 pub visualization: ExampleVisualization,
430 pub editable: bool,
432 pub real_time_feedback: bool,
434}
435
436#[derive(Debug, Clone, Serialize, Deserialize)]
438pub struct InteractiveElement {
439 pub element_type: InteractiveElementType,
441 pub id: String,
443 pub label: String,
445 pub action: String,
447 pub target: String,
449}
450
451#[derive(Debug, Clone, Serialize, Deserialize)]
453pub enum InteractiveElementType {
454 Button,
455 Slider,
456 Toggle,
457 Input,
458 Dropdown,
459}
460
461#[derive(Debug, Clone, Serialize, Deserialize)]
463pub struct ExampleVisualization {
464 pub visualization_type: VisualizationType,
466 pub data: String,
468 pub interactive: bool,
470 pub real_time_updates: bool,
472 pub config: VisualizationConfig,
474}
475
476#[derive(Debug, Clone, Serialize, Deserialize)]
478pub enum VisualizationType {
479 FlowChart,
480 Graph,
481 Timeline,
482 Tree,
483 Network,
484 Chart,
485}
486
487#[derive(Debug, Clone, Serialize, Deserialize)]
489pub struct VisualizationConfig {
490 pub width: u32,
492 pub height: u32,
494 pub theme: String,
496 pub animation_enabled: bool,
498}
499
500#[derive(Debug, Clone, Serialize, Deserialize)]
502pub struct InteractiveTutorial {
503 pub title: String,
505 pub description: String,
507 pub steps: Vec<TutorialStep>,
509 pub difficulty: TutorialDifficulty,
511 pub estimated_time: Duration,
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize)]
517pub struct TutorialStep {
518 pub title: String,
520 pub content: String,
522 pub code_example: Option<CodeExample>,
524 pub interactive_elements: Vec<InteractiveElement>,
526 pub expected_outcome: String,
528}
529
530#[derive(Debug, Clone, Serialize, Deserialize)]
532pub enum TutorialDifficulty {
533 Beginner,
534 Intermediate,
535 Advanced,
536 Expert,
537}
538
539#[derive(Debug, Clone, Serialize, Deserialize)]
541pub struct ApiVisualization {
542 pub title: String,
544 pub visualization_type: VisualizationType,
546 pub data: ApiVisualizationData,
548 pub config: VisualizationConfig,
550}
551
552#[derive(Debug, Clone, Serialize, Deserialize)]
554pub struct ApiVisualizationData {
555 pub nodes: Vec<VisualizationNode>,
557 pub edges: Vec<VisualizationEdge>,
559 pub metadata: HashMap<String, String>,
561}
562
563#[derive(Debug, Clone, Serialize, Deserialize)]
565pub struct VisualizationNode {
566 pub id: String,
568 pub label: String,
570 pub node_type: String,
572 pub properties: HashMap<String, String>,
574}
575
576#[derive(Debug, Clone, Serialize, Deserialize)]
578pub struct VisualizationEdge {
579 pub source: String,
581 pub target: String,
583 pub label: String,
585 pub edge_type: String,
587 pub properties: HashMap<String, String>,
589}
590
591#[derive(Debug, Clone, Serialize, Deserialize)]
597pub struct WasmPlayground {
598 pub html_template: String,
600 pub javascript_code: String,
602 pub css_styling: String,
604 pub rust_code: String,
606 pub build_instructions: Vec<String>,
608}
609
610#[derive(Debug, Clone, Serialize, Deserialize)]
612pub struct WasmBinding {
613 pub rust_name: String,
615 pub js_name: String,
617 pub methods: Vec<WasmMethod>,
619 pub examples: Vec<String>,
621}
622
623#[derive(Debug, Clone, Serialize, Deserialize)]
625pub struct WasmMethod {
626 pub name: String,
628 pub js_signature: String,
630 pub description: String,
632}
633
634#[derive(Debug, Clone, Serialize, Deserialize)]
636pub struct UIComponent {
637 pub name: String,
639 pub component_type: UIComponentType,
641 pub props: Vec<(String, String)>,
643 pub template: String,
645}
646
647#[derive(Debug, Clone, Serialize, Deserialize)]
649pub enum UIComponentType {
650 CodeEditor,
651 OutputPanel,
652 ApiExplorer,
653 ExampleGallery,
654 SearchBox,
655 NavigationMenu,
656}
657
658#[derive(Debug, Clone, Serialize, Deserialize)]
664pub struct SearchIndex {
665 pub items: Vec<SearchItem>,
667 pub metadata: SearchMetadata,
669}
670
671impl SearchIndex {
672 pub fn new() -> Self {
674 Self {
675 items: Vec::new(),
676 metadata: SearchMetadata::default(),
677 }
678 }
679
680 pub fn add_item(&mut self, item: SearchItem) -> Result<()> {
682 self.items.push(item);
683 self.metadata.total_items += 1;
684 Ok(())
685 }
686
687 pub fn search(&self, query: &str) -> Vec<&SearchItem> {
689 self.items
690 .iter()
691 .filter(|item| {
692 item.name.to_lowercase().contains(&query.to_lowercase())
693 || item
694 .description
695 .to_lowercase()
696 .contains(&query.to_lowercase())
697 || item
698 .keywords
699 .iter()
700 .any(|keyword| keyword.to_lowercase().contains(&query.to_lowercase()))
701 })
702 .collect()
703 }
704}
705
706impl Default for SearchIndex {
707 fn default() -> Self {
708 Self::new()
709 }
710}
711
712#[derive(Debug, Clone, Serialize, Deserialize)]
714pub struct SearchItem {
715 pub name: String,
717 pub item_type: SearchItemType,
719 pub description: String,
721 pub path: String,
723 pub keywords: Vec<String>,
725 pub relevance_score: f64,
727}
728
729#[derive(Debug, Clone, Serialize, Deserialize)]
731pub enum SearchItemType {
732 Trait,
733 Type,
734 Method,
735 Function,
736 Example,
737 Tutorial,
738 Documentation,
739}
740
741#[derive(Debug, Clone, Serialize, Deserialize)]
743pub struct SearchMetadata {
744 pub total_items: usize,
746 pub created_at: String,
748 pub updated_at: String,
750 pub version: String,
752}
753
754impl Default for SearchMetadata {
755 fn default() -> Self {
756 let now = chrono::Utc::now().to_string();
757 Self {
758 total_items: 0,
759 created_at: now.clone(),
760 updated_at: now,
761 version: "1.0.0".to_string(),
762 }
763 }
764}
765
766#[derive(Debug, Clone, Serialize, Deserialize)]
768pub struct EnhancedSearchIndex {
769 pub semantic_search: SemanticSearchEngine,
771 pub type_based_search: TypeSearchEngine,
773 pub usage_pattern_search: UsagePatternSearchEngine,
775 pub similarity_search: SimilaritySearchEngine,
777 pub auto_complete_engine: AutoCompleteEngine,
779 pub search_analytics: SearchAnalytics,
781}
782
783#[derive(Debug, Clone, Serialize, Deserialize)]
785pub struct SemanticSearchEngine {
786 pub index: HashMap<String, Vec<f64>>,
788 pub model_config: SemanticModelConfig,
790}
791
792impl SemanticSearchEngine {
793 pub fn new() -> Self {
795 Self {
796 index: HashMap::new(),
797 model_config: SemanticModelConfig::default(),
798 }
799 }
800
801 pub fn index_trait(&mut self, trait_info: &TraitInfo) -> Result<()> {
803 let embedding = vec![0.0; 128]; self.index.insert(trait_info.name.clone(), embedding);
806 Ok(())
807 }
808
809 pub fn index_example(&mut self, example: &CodeExample) -> Result<()> {
811 let embedding = vec![0.0; 128]; self.index.insert(example.title.clone(), embedding);
814 Ok(())
815 }
816}
817
818impl Default for SemanticSearchEngine {
819 fn default() -> Self {
820 Self::new()
821 }
822}
823
824#[derive(Debug, Clone, Serialize, Deserialize)]
826pub struct SemanticModelConfig {
827 pub model_name: String,
829 pub embedding_dim: usize,
831 pub similarity_threshold: f64,
833}
834
835impl Default for SemanticModelConfig {
836 fn default() -> Self {
837 Self {
838 model_name: "sentence-transformers/all-MiniLM-L6-v2".to_string(),
839 embedding_dim: 384,
840 similarity_threshold: 0.7,
841 }
842 }
843}
844
845#[derive(Debug, Clone, Serialize, Deserialize)]
847pub struct TypeSearchEngine {
848 pub signatures: HashMap<String, TypeSignature>,
850 pub compatibility_matrix: HashMap<String, Vec<String>>,
852}
853
854impl TypeSearchEngine {
855 pub fn new() -> Self {
857 Self {
858 signatures: HashMap::new(),
859 compatibility_matrix: HashMap::new(),
860 }
861 }
862
863 pub fn index_trait_signatures(&mut self, trait_info: &TraitInfo) -> Result<()> {
865 for method in &trait_info.methods {
866 self.signatures.insert(
867 method.name.clone(),
868 TypeSignature {
869 signature: method.signature.clone(),
870 return_type: method.return_type.clone(),
871 parameters: method.parameters.clone(),
872 },
873 );
874 }
875 Ok(())
876 }
877
878 pub fn index_type_definition(&mut self, type_info: &TypeInfo) -> Result<()> {
880 self.compatibility_matrix
882 .insert(type_info.name.clone(), type_info.trait_impls.clone());
883 Ok(())
884 }
885}
886
887impl Default for TypeSearchEngine {
888 fn default() -> Self {
889 Self::new()
890 }
891}
892
893#[derive(Debug, Clone, Serialize, Deserialize)]
895pub struct TypeSignature {
896 pub signature: String,
898 pub return_type: String,
900 pub parameters: Vec<ParameterInfo>,
902}
903
904#[derive(Debug, Clone, Serialize, Deserialize)]
906pub struct UsagePatternSearchEngine {
907 pub patterns: HashMap<String, UsagePattern>,
909 pub frequency: HashMap<String, usize>,
911}
912
913impl UsagePatternSearchEngine {
914 pub fn new() -> Self {
916 Self {
917 patterns: HashMap::new(),
918 frequency: HashMap::new(),
919 }
920 }
921
922 pub fn index_usage_patterns(&mut self, example: &CodeExample) -> Result<()> {
924 let pattern = UsagePattern {
926 pattern_type: PatternType::FunctionCall,
927 code_snippet: example.code.clone(),
928 frequency: 1,
929 confidence: 0.8,
930 };
931 self.patterns.insert(example.title.clone(), pattern);
932 Ok(())
933 }
934}
935
936impl Default for UsagePatternSearchEngine {
937 fn default() -> Self {
938 Self::new()
939 }
940}
941
942#[derive(Debug, Clone, Serialize, Deserialize)]
944pub struct UsagePattern {
945 pub pattern_type: PatternType,
947 pub code_snippet: String,
949 pub frequency: usize,
951 pub confidence: f64,
953}
954
955#[derive(Debug, Clone, Serialize, Deserialize)]
957pub enum PatternType {
958 FunctionCall,
959 MethodChaining,
960 ErrorHandling,
961 Initialization,
962 Configuration,
963}
964
965#[derive(Debug, Clone, Serialize, Deserialize)]
967pub struct SimilaritySearchEngine {
968 pub similarity_matrix: HashMap<String, HashMap<String, f64>>,
970 pub algorithms: Vec<SimilarityAlgorithm>,
972}
973
974impl SimilaritySearchEngine {
975 pub fn new() -> Self {
977 Self {
978 similarity_matrix: HashMap::new(),
979 algorithms: vec![SimilarityAlgorithm::Cosine, SimilarityAlgorithm::Jaccard],
980 }
981 }
982
983 pub fn index_trait_similarities(&mut self, trait_info: &TraitInfo) -> Result<()> {
985 let similarities = HashMap::new(); self.similarity_matrix
988 .insert(trait_info.name.clone(), similarities);
989 Ok(())
990 }
991}
992
993impl Default for SimilaritySearchEngine {
994 fn default() -> Self {
995 Self::new()
996 }
997}
998
999#[derive(Debug, Clone, Serialize, Deserialize)]
1001pub enum SimilarityAlgorithm {
1002 Cosine,
1003 Jaccard,
1004 Euclidean,
1005 Manhattan,
1006}
1007
1008#[derive(Debug, Clone, Serialize, Deserialize)]
1010pub struct AutoCompleteEngine {
1011 pub completions: HashMap<String, CompletionNode>,
1013 pub stats: CompletionStats,
1015}
1016
1017impl AutoCompleteEngine {
1018 pub fn new() -> Self {
1020 Self {
1021 completions: HashMap::new(),
1022 stats: CompletionStats::default(),
1023 }
1024 }
1025
1026 pub fn add_completion(&mut self, text: &str, completion_type: CompletionType) -> Result<()> {
1028 let node = CompletionNode {
1029 text: text.to_string(),
1030 completion_type,
1031 frequency: 1,
1032 score: 1.0,
1033 };
1034 self.completions.insert(text.to_string(), node);
1035 self.stats.total_completions += 1;
1036 Ok(())
1037 }
1038
1039 pub fn get_completions(&self, prefix: &str) -> Vec<&CompletionNode> {
1041 self.completions
1042 .values()
1043 .filter(|node| node.text.starts_with(prefix))
1044 .collect()
1045 }
1046}
1047
1048impl Default for AutoCompleteEngine {
1049 fn default() -> Self {
1050 Self::new()
1051 }
1052}
1053
1054#[derive(Debug, Clone, Serialize, Deserialize)]
1056pub struct CompletionNode {
1057 pub text: String,
1059 pub completion_type: CompletionType,
1061 pub frequency: usize,
1063 pub score: f64,
1065}
1066
1067#[derive(Debug, Clone, Serialize, Deserialize)]
1069pub enum CompletionType {
1070 Trait,
1071 Type,
1072 Method,
1073 Function,
1074 Variable,
1075 Keyword,
1076}
1077
1078#[derive(Debug, Clone, Serialize, Deserialize)]
1080pub struct CompletionStats {
1081 pub total_completions: usize,
1083 pub popular_completions: Vec<String>,
1085 pub accuracy: f64,
1087}
1088
1089impl Default for CompletionStats {
1090 fn default() -> Self {
1091 Self {
1092 total_completions: 0,
1093 popular_completions: Vec::new(),
1094 accuracy: 0.0,
1095 }
1096 }
1097}
1098
1099#[derive(Debug, Clone, Serialize, Deserialize)]
1101pub struct SearchAnalytics {
1102 pub query_count: usize,
1104 pub popular_queries: Vec<String>,
1106 pub performance_metrics: SearchPerformanceMetrics,
1108}
1109
1110impl SearchAnalytics {
1111 pub fn new() -> Self {
1113 Self {
1114 query_count: 0,
1115 popular_queries: Vec::new(),
1116 performance_metrics: SearchPerformanceMetrics::default(),
1117 }
1118 }
1119}
1120
1121impl Default for SearchAnalytics {
1122 fn default() -> Self {
1123 Self::new()
1124 }
1125}
1126
1127#[derive(Debug, Clone, Serialize, Deserialize)]
1129pub struct SearchPerformanceMetrics {
1130 pub avg_search_time_ms: f64,
1132 pub success_rate: f64,
1134 pub index_size_bytes: usize,
1136}
1137
1138impl Default for SearchPerformanceMetrics {
1139 fn default() -> Self {
1140 Self {
1141 avg_search_time_ms: 0.0,
1142 success_rate: 0.0,
1143 index_size_bytes: 0,
1144 }
1145 }
1146}
1147
1148#[derive(Debug, Clone, Serialize, Deserialize)]
1154pub struct TutorialTemplate {
1155 pub name: String,
1157 pub content: String,
1159 pub variables: HashMap<String, String>,
1161 pub required_elements: Vec<String>,
1163}
1164
1165#[allow(non_snake_case)]
1170#[cfg(test)]
1171mod tests {
1172 use super::*;
1173
1174 #[test]
1175 fn test_api_reference_creation() {
1176 let api_ref = ApiReference {
1177 crate_name: "test-crate".to_string(),
1178 version: "1.0.0".to_string(),
1179 traits: Vec::new(),
1180 types: Vec::new(),
1181 examples: Vec::new(),
1182 cross_references: HashMap::new(),
1183 metadata: ApiMetadata::default(),
1184 };
1185
1186 assert_eq!(api_ref.crate_name, "test-crate");
1187 assert_eq!(api_ref.version, "1.0.0");
1188 }
1189
1190 #[test]
1191 fn test_search_index() {
1192 let mut index = SearchIndex::new();
1193 let item = SearchItem {
1194 name: "TestTrait".to_string(),
1195 item_type: SearchItemType::Trait,
1196 description: "A test trait".to_string(),
1197 path: "test::TestTrait".to_string(),
1198 keywords: vec!["test".to_string(), "trait".to_string()],
1199 relevance_score: 1.0,
1200 };
1201
1202 index.add_item(item).expect("add_item should succeed");
1203 assert_eq!(index.items.len(), 1);
1204 assert_eq!(index.metadata.total_items, 1);
1205
1206 let results = index.search("test");
1207 assert_eq!(results.len(), 1);
1208 assert_eq!(results[0].name, "TestTrait");
1209 }
1210
1211 #[test]
1212 fn test_trait_info_default() {
1213 let trait_info = TraitInfo::default();
1214 assert!(trait_info.name.is_empty());
1215 assert!(trait_info.methods.is_empty());
1216 assert!(trait_info.associated_types.is_empty());
1217 }
1218
1219 #[test]
1220 fn test_code_example() {
1221 let example = CodeExample {
1222 title: "Basic Usage".to_string(),
1223 description: "Shows basic usage".to_string(),
1224 code: "fn main() {}".to_string(),
1225 language: "rust".to_string(),
1226 runnable: true,
1227 expected_output: Some("Success".to_string()),
1228 };
1229
1230 assert_eq!(example.title, "Basic Usage");
1231 assert!(example.runnable);
1232 }
1233
1234 #[test]
1235 fn test_auto_complete_engine() {
1236 let mut engine = AutoCompleteEngine::new();
1237 engine
1238 .add_completion("TestTrait", CompletionType::Trait)
1239 .expect("expected valid value");
1240 engine
1241 .add_completion("TestType", CompletionType::Type)
1242 .expect("expected valid value");
1243
1244 let completions = engine.get_completions("Test");
1245 assert_eq!(completions.len(), 2);
1246
1247 let completions = engine.get_completions("TestT");
1248 assert_eq!(completions.len(), 2);
1249
1250 let completions = engine.get_completions("TestTr");
1251 assert_eq!(completions.len(), 1);
1252 assert_eq!(completions[0].text, "TestTrait");
1253 }
1254
1255 #[test]
1256 fn test_serialization() {
1257 let example = CodeExample {
1258 title: "Test".to_string(),
1259 description: "Test example".to_string(),
1260 code: "println!(\"Hello\");".to_string(),
1261 language: "rust".to_string(),
1262 runnable: true,
1263 expected_output: None,
1264 };
1265
1266 let serialized = serde_json::to_string(&example).unwrap_or_default();
1267 let deserialized: CodeExample =
1268 serde_json::from_str(&serialized).expect("valid JSON operation");
1269
1270 assert_eq!(example.title, deserialized.title);
1271 assert_eq!(example.code, deserialized.code);
1272 }
1273
1274 #[test]
1275 fn test_visibility_display() {
1276 assert_eq!(Visibility::Public.to_string(), "public");
1277 assert_eq!(Visibility::Private.to_string(), "private");
1278 assert_eq!(
1279 Visibility::Restricted("crate".to_string()).to_string(),
1280 "restricted(crate)"
1281 );
1282 }
1283}