ruchy/wasm/
portability.rs

1//! Portability scoring for WebAssembly components (RUCHY-0819)
2//!
3//! Analyzes and scores the portability of Ruchy-generated WASM components
4//! across different platforms and runtimes.
5
6#[cfg(test)]
7mod tests {
8    use super::*;
9    
10    use std::collections::{HashMap, HashSet};
11    
12    // Helper functions for consistent test setup
13    fn create_test_config() -> AnalysisConfig {
14        AnalysisConfig {
15            target_platforms: vec![
16                "wasmtime".to_string(),
17                "wasmer".to_string(),
18                "browser".to_string(),
19            ],
20            check_api_compatibility: true,
21            check_size_constraints: true,
22            check_performance: true,
23            check_security: true,
24            strict_mode: false,
25        }
26    }
27    
28    fn create_test_component_info() -> ComponentInfo {
29        let mut features = HashSet::new();
30        features.insert("memory".to_string());
31        features.insert("tables".to_string());
32        
33        ComponentInfo {
34            name: "test_component".to_string(),
35            version: "1.0.0".to_string(),
36            size: 1024 * 10, // 10KB
37            exports_count: 5,
38            imports_count: 3,
39            features,
40        }
41    }
42    
43    fn create_test_portability_score() -> PortabilityScore {
44        let mut platform_scores = HashMap::new();
45        platform_scores.insert("wasmtime".to_string(), 0.95);
46        platform_scores.insert("wasmer".to_string(), 0.92);
47        platform_scores.insert("browser".to_string(), 0.88);
48        
49        let mut feature_scores = HashMap::new();
50        feature_scores.insert("memory".to_string(), 0.9);
51        feature_scores.insert("threading".to_string(), 0.7);
52        feature_scores.insert("simd".to_string(), 0.6);
53        
54        PortabilityScore {
55            overall_score: 0.85,
56            platform_scores,
57            feature_scores,
58            api_compatibility: 0.90,
59            size_efficiency: 0.88,
60            performance_portability: 0.82,
61            security_compliance: 0.95,
62        }
63    }
64    
65    fn create_test_analyzer() -> PortabilityAnalyzer {
66        PortabilityAnalyzer::new()
67    }
68    
69    fn create_test_analyzer_with_config() -> PortabilityAnalyzer {
70        let config = create_test_config();
71        PortabilityAnalyzer::new_with_config(config)
72    }
73    
74    // ========== AnalysisConfig Tests ==========
75    
76    #[test]
77    fn test_analysis_config_creation() {
78        let config = create_test_config();
79        assert_eq!(config.target_platforms.len(), 3);
80        assert!(config.check_api_compatibility);
81        assert!(config.check_size_constraints);
82        assert!(config.check_performance);
83        assert!(config.check_security);
84        assert!(!config.strict_mode);
85    }
86    
87    #[test]
88    fn test_analysis_config_default() {
89        let config = AnalysisConfig::default();
90        assert!(!config.target_platforms.is_empty());
91        assert!(config.check_api_compatibility);
92        assert!(!config.strict_mode);
93    }
94    
95    #[test]
96    fn test_analysis_config_clone() {
97        let config1 = create_test_config();
98        let config2 = config1.clone();
99        assert_eq!(config1.target_platforms, config2.target_platforms);
100        assert_eq!(config1.strict_mode, config2.strict_mode);
101    }
102    
103    #[test]
104    fn test_analysis_config_serialization() {
105        let config = create_test_config();
106        let json = serde_json::to_string(&config).unwrap();
107        let deserialized: AnalysisConfig = serde_json::from_str(&json).unwrap();
108        assert_eq!(config.target_platforms, deserialized.target_platforms);
109    }
110    
111    // ========== ComponentInfo Tests ==========
112    
113    #[test]
114    fn test_component_info_creation() {
115        let info = create_test_component_info();
116        assert_eq!(info.name, "test_component");
117        assert_eq!(info.version, "1.0.0");
118        assert_eq!(info.size, 10240);
119        assert_eq!(info.exports_count, 5);
120        assert_eq!(info.imports_count, 3);
121        assert_eq!(info.features.len(), 2);
122    }
123    
124    #[test]
125    fn test_component_info_without_features() {
126        let info = ComponentInfo {
127            name: "minimal".to_string(),
128            version: "0.1.0".to_string(),
129            size: 1024,
130            exports_count: 0,
131            imports_count: 0,
132            features: HashSet::new(),
133        };
134        assert_eq!(info.exports_count, 0);
135        assert_eq!(info.imports_count, 0);
136        assert!(info.features.is_empty());
137    }
138    
139    #[test]
140    fn test_component_info_serialization() {
141        let info = create_test_component_info();
142        let json = serde_json::to_string(&info).unwrap();
143        let deserialized: ComponentInfo = serde_json::from_str(&json).unwrap();
144        assert_eq!(info.name, deserialized.name);
145        assert_eq!(info.size, deserialized.size);
146    }
147    
148    // ========== PortabilityScore Tests ==========
149    
150    #[test]
151    fn test_portability_score_creation() {
152        let score = create_test_portability_score();
153        assert_eq!(score.overall_score, 0.85);
154        assert_eq!(score.platform_scores.len(), 3);
155        assert_eq!(score.feature_scores.len(), 3);
156        assert_eq!(score.api_compatibility, 0.90);
157        assert_eq!(score.security_compliance, 0.95);
158    }
159    
160    #[test]
161    fn test_portability_score_platform_lookup() {
162        let score = create_test_portability_score();
163        assert_eq!(*score.platform_scores.get("wasmtime").unwrap(), 0.95);
164        assert_eq!(*score.platform_scores.get("wasmer").unwrap(), 0.92);
165        assert_eq!(*score.platform_scores.get("browser").unwrap(), 0.88);
166    }
167    
168    #[test]
169    fn test_portability_score_feature_lookup() {
170        let score = create_test_portability_score();
171        assert_eq!(*score.feature_scores.get("memory").unwrap(), 0.9);
172        assert_eq!(*score.feature_scores.get("threading").unwrap(), 0.7);
173        assert_eq!(*score.feature_scores.get("simd").unwrap(), 0.6);
174    }
175    
176    #[test]
177    fn test_portability_score_perfect() {
178        let mut score = create_test_portability_score();
179        score.overall_score = 1.0;
180        score.api_compatibility = 1.0;
181        score.size_efficiency = 1.0;
182        score.performance_portability = 1.0;
183        score.security_compliance = 1.0;
184        
185        assert_eq!(score.overall_score, 1.0);
186        assert_eq!(score.api_compatibility, 1.0);
187        assert_eq!(score.size_efficiency, 1.0);
188        assert_eq!(score.performance_portability, 1.0);
189        assert_eq!(score.security_compliance, 1.0);
190    }
191    
192    #[test]
193    fn test_portability_score_failing() {
194        let mut score = create_test_portability_score();
195        score.overall_score = 0.4;
196        assert!(score.overall_score < 0.5);
197    }
198    
199    // ========== CompatibilityIssue Tests ==========
200    
201    #[test]
202    fn test_compatibility_issue_creation() {
203        let issue = CompatibilityIssue {
204            severity: IssueSeverity::Warning,
205            category: IssueCategory::ApiIncompatibility,
206            affected_platforms: vec!["browser".to_string()],
207            description: "Missing API support".to_string(),
208            fix_suggestion: Some("Use polyfill or alternative API".to_string()),
209        };
210        
211        assert_eq!(issue.severity, IssueSeverity::Warning);
212        assert_eq!(issue.category, IssueCategory::ApiIncompatibility);
213        assert_eq!(issue.affected_platforms.len(), 1);
214        assert!(issue.fix_suggestion.is_some());
215    }
216    
217    #[test]
218    fn test_compatibility_issue_severity_levels() {
219        let severities = [IssueSeverity::Error,
220            IssueSeverity::Warning,
221            IssueSeverity::Info];
222        
223        assert_eq!(severities.len(), 3);
224        assert_ne!(severities[0], severities[1]);
225    }
226    
227    #[test]
228    fn test_compatibility_issue_categories() {
229        let categories = [IssueCategory::ApiIncompatibility,
230            IssueCategory::FeatureNotSupported,
231            IssueCategory::Performance,
232            IssueCategory::SizeConstraint,
233            IssueCategory::Security,
234            IssueCategory::Configuration];
235        
236        assert_eq!(categories.len(), 6);
237    }
238    
239    // ========== Recommendation Tests ==========
240    
241    #[test]
242    fn test_recommendation_creation() {
243        let rec = Recommendation {
244            priority: RecommendationPriority::High,
245            title: "Optimize memory usage".to_string(),
246            description: "Reduce memory allocation".to_string(),
247            impact: 0.1,
248            platforms: vec!["wasmtime".to_string(), "wasmer".to_string()],
249        };
250        
251        assert_eq!(rec.priority, RecommendationPriority::High);
252        assert_eq!(rec.title, "Optimize memory usage");
253        assert_eq!(rec.impact, 0.1);
254        assert_eq!(rec.platforms.len(), 2);
255    }
256    
257    #[test]
258    fn test_recommendation_priorities() {
259        let priorities = [RecommendationPriority::Low,
260            RecommendationPriority::Medium,
261            RecommendationPriority::High];
262        
263        assert_eq!(priorities.len(), 3);
264    }
265    
266    #[test]
267    fn test_recommendation_serialization() {
268        let rec = Recommendation {
269            priority: RecommendationPriority::Medium,
270            title: "Test recommendation".to_string(),
271            description: "Test description".to_string(),
272            impact: 0.05,
273            platforms: vec!["browser".to_string()],
274        };
275        
276        let json = serde_json::to_string(&rec).unwrap();
277        let deserialized: Recommendation = serde_json::from_str(&json).unwrap();
278        assert_eq!(rec.title, deserialized.title);
279        assert_eq!(rec.impact, deserialized.impact);
280    }
281    
282    // ========== PlatformSupport Tests ==========
283    
284    #[test]
285    fn test_platform_support_creation() {
286        let support = PlatformSupport {
287            platform: "wasmtime".to_string(),
288            support_level: SupportLevel::Full,
289            compatibility_score: 0.9,
290            required_modifications: vec![],
291            runtime_requirements: Some("1.0-2.0".to_string()),
292        };
293        
294        assert_eq!(support.platform, "wasmtime");
295        assert_eq!(support.support_level, SupportLevel::Full);
296        assert!(support.required_modifications.is_empty());
297        assert_eq!(support.compatibility_score, 0.9);
298    }
299    
300    #[test]
301    fn test_platform_support_partial() {
302        let support = PlatformSupport {
303            platform: "browser".to_string(),
304            support_level: SupportLevel::Partial,
305            compatibility_score: 0.7,
306            required_modifications: vec!["Remove filesystem access".to_string()],
307            runtime_requirements: None,
308        };
309        
310        assert_eq!(support.support_level, SupportLevel::Partial);
311        assert_eq!(support.required_modifications.len(), 1);
312        assert_eq!(support.compatibility_score, 0.7);
313        assert!(support.runtime_requirements.is_none());
314    }
315    
316    // ========== FeatureUsage Tests ==========
317    
318    #[test]
319    fn test_feature_usage_creation() {
320        let mut core = HashSet::new();
321        core.insert("memory".to_string());
322        core.insert("tables".to_string());
323        
324        let mut proposal = HashSet::new();
325        proposal.insert("simd".to_string());
326        
327        let usage = FeatureUsage {
328            core_features: core,
329            proposal_features: proposal,
330            platform_specific: HashMap::new(),
331            compatibility: HashMap::new(),
332        };
333        
334        assert_eq!(usage.core_features.len(), 2);
335        assert_eq!(usage.proposal_features.len(), 1);
336        assert!(usage.platform_specific.is_empty());
337    }
338    
339    #[test]
340    fn test_feature_usage_with_proposals() {
341        let mut proposals = HashSet::new();
342        proposals.insert("threads".to_string());
343        proposals.insert("simd".to_string());
344        
345        let usage = FeatureUsage {
346            core_features: HashSet::new(),
347            proposal_features: proposals,
348            platform_specific: HashMap::new(),
349            compatibility: HashMap::new(),
350        };
351        
352        assert_eq!(usage.proposal_features.len(), 2);
353        assert!(usage.proposal_features.contains(&"threads".to_string()));
354    }
355    
356    // ========== SizeAnalysis Tests ==========
357    
358    #[test]
359    fn test_size_analysis_creation() {
360        let analysis = SizeAnalysis {
361            total_size: 10240,
362            code_size: 6000,
363            data_size: 2000,
364            custom_sections_size: 1240,
365            section_sizes: HashMap::new(),
366            platform_limits: HashMap::new(),
367        };
368        
369        assert_eq!(analysis.total_size, 10240);
370        assert_eq!(analysis.code_size, 6000);
371        assert_eq!(analysis.data_size, 2000);
372        assert_eq!(analysis.custom_sections_size, 1240);
373    }
374    
375    #[test]
376    fn test_size_analysis_with_sections() {
377        let mut sections = HashMap::new();
378        sections.insert("code".to_string(), 6000);
379        sections.insert("data".to_string(), 2000);
380        sections.insert("debug".to_string(), 500);
381        
382        let analysis = SizeAnalysis {
383            total_size: 10240,
384            code_size: 6000,
385            data_size: 2000,
386            custom_sections_size: 1500,
387            section_sizes: sections,
388            platform_limits: HashMap::new(),
389        };
390        
391        assert_eq!(analysis.section_sizes.len(), 3);
392        assert_eq!(*analysis.section_sizes.get("debug").unwrap(), 500);
393    }
394    
395    // ========== PortabilityAnalyzer Tests ==========
396    
397    #[test]
398    fn test_analyzer_creation() {
399        let analyzer = create_test_analyzer();
400        // Default config has 6 platforms
401        assert_eq!(analyzer.config.target_platforms.len(), 6);
402    }
403    
404    #[test]
405    fn test_analyzer_with_custom_config() {
406        let mut config = create_test_config();
407        config.strict_mode = true;
408        config.check_performance = false;
409        
410        let analyzer = PortabilityAnalyzer::new_with_config(config);
411        assert!(analyzer.config.strict_mode);
412        assert!(!analyzer.config.check_performance);
413    }
414    
415    #[test]
416    fn test_analyzer_default_config() {
417        let analyzer = create_test_analyzer();
418        // Test that analyzer is created successfully
419        assert!(analyzer.config.check_api_compatibility);
420        assert!(analyzer.config.check_size_constraints);
421        assert!(analyzer.config.check_performance);
422        assert!(analyzer.config.check_security);
423    }
424    
425    #[test]
426    fn test_analyzer_custom_config() {
427        let analyzer = create_test_analyzer_with_config();
428        // Verify custom config is applied
429        assert_eq!(analyzer.config.target_platforms.len(), 3);
430        assert!(analyzer.config.target_platforms.contains(&"wasmtime".to_string()));
431        assert!(analyzer.config.target_platforms.contains(&"wasmer".to_string()));
432        assert!(analyzer.config.target_platforms.contains(&"browser".to_string()));
433    }
434    
435    #[test]
436    fn test_analyzer_strict_mode() {
437        let mut config = create_test_config();
438        config.strict_mode = true;
439        let analyzer = PortabilityAnalyzer::new_with_config(config);
440        assert!(analyzer.config.strict_mode);
441        
442        // Test non-strict mode
443        let mut config2 = create_test_config();
444        config2.strict_mode = false;
445        let analyzer2 = PortabilityAnalyzer::new_with_config(config2);
446        assert!(!analyzer2.config.strict_mode);
447    }
448    
449    // ========== PortabilityReport Tests ==========
450    
451    #[test]
452    fn test_portability_report_creation() {
453        let report = PortabilityReport {
454            component_info: create_test_component_info(),
455            score: create_test_portability_score(),
456            issues: vec![],
457            recommendations: vec![],
458            platform_support: HashMap::new(),
459            feature_usage: FeatureUsage {
460                core_features: HashSet::new(),
461                proposal_features: HashSet::new(),
462                platform_specific: HashMap::new(),
463                compatibility: HashMap::new(),
464            },
465            size_analysis: SizeAnalysis {
466                total_size: 0,
467                code_size: 0,
468                data_size: 0,
469                custom_sections_size: 0,
470                section_sizes: HashMap::new(),
471                platform_limits: HashMap::new(),
472            },
473        };
474        
475        assert_eq!(report.component_info.name, "test_component");
476        assert_eq!(report.score.overall_score, 0.85);
477        assert!(report.issues.is_empty());
478        assert!(report.recommendations.is_empty());
479    }
480    
481    #[test]
482    fn test_portability_report_with_issues() {
483        let issue = CompatibilityIssue {
484            severity: IssueSeverity::Warning,
485            category: IssueCategory::FeatureNotSupported,
486            affected_platforms: vec!["browser".to_string()],
487            description: "Threading not supported".to_string(),
488            fix_suggestion: Some("Use web workers".to_string()),
489        };
490        
491        let report = PortabilityReport {
492            component_info: create_test_component_info(),
493            score: create_test_portability_score(),
494            issues: vec![issue],
495            recommendations: vec![],
496            platform_support: HashMap::new(),
497            feature_usage: FeatureUsage {
498                core_features: HashSet::new(),
499                proposal_features: HashSet::new(),
500                platform_specific: HashMap::new(),
501                compatibility: HashMap::new(),
502            },
503            size_analysis: SizeAnalysis {
504                total_size: 0,
505                code_size: 0,
506                data_size: 0,
507                custom_sections_size: 0,
508                section_sizes: HashMap::new(),
509                platform_limits: HashMap::new(),
510            },
511        };
512        
513        assert_eq!(report.issues.len(), 1);
514        assert_eq!(report.issues[0].severity, IssueSeverity::Warning);
515    }
516    
517    #[test]
518    fn test_portability_report_serialization() {
519        let report = PortabilityReport {
520            component_info: create_test_component_info(),
521            score: create_test_portability_score(),
522            issues: vec![],
523            recommendations: vec![],
524            platform_support: HashMap::new(),
525            feature_usage: FeatureUsage {
526                core_features: HashSet::new(),
527                proposal_features: HashSet::new(),
528                platform_specific: HashMap::new(),
529                compatibility: HashMap::new(),
530            },
531            size_analysis: SizeAnalysis {
532                total_size: 0,
533                code_size: 0,
534                data_size: 0,
535                custom_sections_size: 0,
536                section_sizes: HashMap::new(),
537                platform_limits: HashMap::new(),
538            },
539        };
540        
541        let json = serde_json::to_string(&report).unwrap();
542        let deserialized: PortabilityReport = serde_json::from_str(&json).unwrap();
543        
544        assert_eq!(report.component_info.name, deserialized.component_info.name);
545        assert_eq!(report.score.overall_score, deserialized.score.overall_score);
546    }
547    
548    // ========== Integration Tests ==========
549    
550    #[test]
551    fn test_full_portability_analysis_workflow() {
552        // Test creating complete portability report
553        let report = PortabilityReport {
554            component_info: create_test_component_info(),
555            score: create_test_portability_score(),
556            issues: vec![
557                CompatibilityIssue {
558                    severity: IssueSeverity::Info,
559                    category: IssueCategory::Performance,
560                    affected_platforms: vec!["browser".to_string()],
561                    description: "Performance may vary".to_string(),
562                    fix_suggestion: None,
563                },
564            ],
565            recommendations: vec![
566                Recommendation {
567                    priority: RecommendationPriority::Low,
568                    title: "Consider optimization".to_string(),
569                    description: "Optimize for browser platform".to_string(),
570                    impact: 0.05,
571                    platforms: vec!["browser".to_string()],
572                },
573            ],
574            platform_support: HashMap::new(),
575            feature_usage: FeatureUsage {
576                core_features: HashSet::new(),
577                proposal_features: HashSet::new(),
578                platform_specific: HashMap::new(),
579                compatibility: HashMap::new(),
580            },
581            size_analysis: SizeAnalysis {
582                total_size: 10240,
583                code_size: 6000,
584                data_size: 2000,
585                custom_sections_size: 1240,
586                section_sizes: HashMap::new(),
587                platform_limits: HashMap::new(),
588            },
589        };
590        
591        // Check report completeness
592        assert!(!report.component_info.name.is_empty());
593        assert!(report.score.overall_score >= 0.0);
594        assert!(report.score.overall_score <= 1.0);
595        assert_eq!(report.issues.len(), 1);
596        assert_eq!(report.recommendations.len(), 1);
597    }
598    
599    #[test]
600    fn test_enum_variants() {
601        // Test all IssueSeverity variants
602        let severities = vec![
603            IssueSeverity::Error,
604            IssueSeverity::Warning,
605            IssueSeverity::Info,
606        ];
607        for s in &severities {
608            assert!(matches!(s, IssueSeverity::Error | IssueSeverity::Warning | IssueSeverity::Info));
609        }
610        
611        // Test all IssueCategory variants
612        let categories = [IssueCategory::ApiIncompatibility,
613            IssueCategory::FeatureNotSupported,
614            IssueCategory::SizeConstraint,
615            IssueCategory::Performance,
616            IssueCategory::Security,
617            IssueCategory::Configuration];
618        assert_eq!(categories.len(), 6);
619        
620        // Test RecommendationPriority variants
621        let priorities = [RecommendationPriority::Low,
622            RecommendationPriority::Medium,
623            RecommendationPriority::High];
624        assert_eq!(priorities.len(), 3);
625        
626        // Test SupportLevel variants
627        let levels = [SupportLevel::Full,
628            SupportLevel::Partial,
629            SupportLevel::None];
630        assert_eq!(levels.len(), 3);
631    }
632    
633    #[test]
634    fn test_complex_portability_score() {
635        let mut platform_scores = HashMap::new();
636        platform_scores.insert("wasmtime".to_string(), 1.0);
637        platform_scores.insert("wasmer".to_string(), 0.95);
638        platform_scores.insert("browser".to_string(), 0.75);
639        platform_scores.insert("node".to_string(), 0.85);
640        
641        let mut feature_scores = HashMap::new();
642        feature_scores.insert("memory".to_string(), 1.0);
643        feature_scores.insert("tables".to_string(), 1.0);
644        feature_scores.insert("threading".to_string(), 0.5);
645        feature_scores.insert("simd".to_string(), 0.8);
646        feature_scores.insert("bulk-memory".to_string(), 0.9);
647        
648        let score = PortabilityScore {
649            overall_score: 0.875,
650            platform_scores,
651            feature_scores,
652            api_compatibility: 0.92,
653            size_efficiency: 0.95,
654            performance_portability: 0.78,
655            security_compliance: 1.0,
656        };
657        
658        assert_eq!(score.platform_scores.len(), 4);
659        assert_eq!(score.feature_scores.len(), 5);
660        assert_eq!(score.security_compliance, 1.0);
661    }
662    
663    #[test]
664    fn test_edge_case_scores() {
665        // Test minimum scores
666        let min_score = PortabilityScore {
667            overall_score: 0.0,
668            platform_scores: HashMap::new(),
669            feature_scores: HashMap::new(),
670            api_compatibility: 0.0,
671            size_efficiency: 0.0,
672            performance_portability: 0.0,
673            security_compliance: 0.0,
674        };
675        
676        assert_eq!(min_score.overall_score, 0.0);
677        assert!(min_score.platform_scores.is_empty());
678        
679        // Test maximum scores
680        let mut perfect_platforms = HashMap::new();
681        perfect_platforms.insert("all".to_string(), 1.0);
682        
683        let max_score = PortabilityScore {
684            overall_score: 1.0,
685            platform_scores: perfect_platforms,
686            feature_scores: HashMap::new(),
687            api_compatibility: 1.0,
688            size_efficiency: 1.0,
689            performance_portability: 1.0,
690            security_compliance: 1.0,
691        };
692        
693        assert_eq!(max_score.overall_score, 1.0);
694        assert_eq!(max_score.api_compatibility, 1.0);
695    }
696    
697    #[test]
698    fn test_component_info_edge_cases() {
699        // Test component with maximum values
700        let mut max_features = HashSet::new();
701        for i in 0..20 {
702            max_features.insert(format!("feature_{i}"));
703        }
704        
705        let large_component = ComponentInfo {
706            name: "large_component".to_string(),
707            version: "99.99.99".to_string(),
708            size: usize::MAX,
709            exports_count: 1000,
710            imports_count: 500,
711            features: max_features,
712        };
713        
714        assert_eq!(large_component.features.len(), 20);
715        assert_eq!(large_component.exports_count, 1000);
716        assert_eq!(large_component.size, usize::MAX);
717        
718        // Test component with minimum values
719        let minimal_component = ComponentInfo {
720            name: String::new(),
721            version: String::new(),
722            size: 0,
723            exports_count: 0,
724            imports_count: 0,
725            features: HashSet::new(),
726        };
727        
728        assert!(minimal_component.name.is_empty());
729        assert_eq!(minimal_component.size, 0);
730    }
731    
732    #[test]
733    fn test_platform_support_variations() {
734        let support_variations = vec![
735            PlatformSupport {
736                platform: "wasmtime".to_string(),
737                support_level: SupportLevel::Full,
738                compatibility_score: 1.0,
739                required_modifications: vec![],
740                runtime_requirements: Some(">=1.0.0".to_string()),
741            },
742            PlatformSupport {
743                platform: "wasmer".to_string(),
744                support_level: SupportLevel::Partial,
745                compatibility_score: 0.8,
746                required_modifications: vec!["Remove SIMD".to_string()],
747                runtime_requirements: Some(">=2.0.0".to_string()),
748            },
749            PlatformSupport {
750                platform: "browser".to_string(),
751                support_level: SupportLevel::None,
752                compatibility_score: 0.0,
753                required_modifications: vec!["Complete rewrite".to_string()],
754                runtime_requirements: None,
755            },
756        ];
757        
758        assert_eq!(support_variations.len(), 3);
759        assert_eq!(support_variations[0].support_level, SupportLevel::Full);
760        assert_eq!(support_variations[1].support_level, SupportLevel::Partial);
761        assert_eq!(support_variations[2].support_level, SupportLevel::None);
762    }
763    
764    #[test]
765    fn test_feature_usage_complex() {
766        let mut core_features = HashSet::new();
767        core_features.insert("memory".to_string());
768        core_features.insert("tables".to_string());
769        core_features.insert("globals".to_string());
770        
771        let mut proposal_features = HashSet::new();
772        proposal_features.insert("threads".to_string());
773        proposal_features.insert("simd".to_string());
774        proposal_features.insert("reference-types".to_string());
775        
776        let mut platform_specific = HashMap::new();
777        let mut browser_features = HashSet::new();
778        browser_features.insert("webgl".to_string());
779        platform_specific.insert("browser".to_string(), browser_features);
780        
781        let usage = FeatureUsage {
782            core_features: core_features.clone(),
783            proposal_features: proposal_features.clone(),
784            platform_specific,
785            compatibility: HashMap::new(),
786        };
787        
788        assert_eq!(usage.core_features.len(), 3);
789        assert_eq!(usage.proposal_features.len(), 3);
790        assert_eq!(usage.platform_specific.len(), 1);
791        assert!(usage.core_features.contains("memory"));
792        assert!(usage.proposal_features.contains("threads"));
793    }
794    
795    #[test]
796    fn test_size_analysis_comprehensive() {
797        let mut section_sizes = HashMap::new();
798        section_sizes.insert("type".to_string(), 1024);
799        section_sizes.insert("import".to_string(), 512);
800        section_sizes.insert("function".to_string(), 256);
801        section_sizes.insert("table".to_string(), 128);
802        section_sizes.insert("memory".to_string(), 64);
803        section_sizes.insert("global".to_string(), 32);
804        section_sizes.insert("export".to_string(), 256);
805        section_sizes.insert("start".to_string(), 8);
806        section_sizes.insert("element".to_string(), 512);
807        section_sizes.insert("code".to_string(), 8192);
808        section_sizes.insert("data".to_string(), 4096);
809        
810        let mut platform_limits = HashMap::new();
811        platform_limits.insert("browser".to_string(), 1024 * 1024 * 4); // 4MB
812        platform_limits.insert("wasmtime".to_string(), 1024 * 1024 * 1024); // 1GB
813        
814        let analysis = SizeAnalysis {
815            total_size: 15080,
816            code_size: 8192,
817            data_size: 4096,
818            custom_sections_size: 0,
819            section_sizes,
820            platform_limits,
821        };
822        
823        assert_eq!(analysis.section_sizes.len(), 11);
824        assert_eq!(analysis.platform_limits.len(), 2);
825        assert_eq!(*analysis.section_sizes.get("code").unwrap(), 8192);
826        assert_eq!(*analysis.platform_limits.get("browser").unwrap(), 4_194_304);
827    }
828}
829
830use anyhow::Result;
831use serde::{Deserialize, Serialize};
832use std::collections::{HashMap, HashSet};
833use std::fmt;
834use super::component::WasmComponent;
835
836/// Portability analyzer for WASM components
837pub struct PortabilityAnalyzer {
838    /// Analysis configuration
839    config: AnalysisConfig,
840    
841    /// Feature compatibility matrix
842    compatibility_matrix: CompatibilityMatrix,
843    
844    /// Platform requirements
845    platform_requirements: HashMap<String, PlatformRequirements>,
846}
847
848/// Portability score for a component
849#[derive(Debug, Clone, Serialize, Deserialize)]
850pub struct PortabilityScore {
851    /// Overall portability score (0.0 - 1.0)
852    pub overall_score: f64,
853    
854    /// Platform-specific scores
855    pub platform_scores: HashMap<String, f64>,
856    
857    /// Feature compatibility scores
858    pub feature_scores: HashMap<String, f64>,
859    
860    /// API compatibility score
861    pub api_compatibility: f64,
862    
863    /// Size efficiency score
864    pub size_efficiency: f64,
865    
866    /// Performance portability score
867    pub performance_portability: f64,
868    
869    /// Safety compliance score
870    pub security_compliance: f64,
871}
872
873/// Detailed portability report
874#[derive(Debug, Clone, Serialize, Deserialize)]
875pub struct PortabilityReport {
876    /// Component information
877    pub component_info: ComponentInfo,
878    
879    /// Portability score
880    pub score: PortabilityScore,
881    
882    /// Compatibility issues
883    pub issues: Vec<CompatibilityIssue>,
884    
885    /// Recommendations
886    pub recommendations: Vec<Recommendation>,
887    
888    /// Platform support matrix
889    pub platform_support: HashMap<String, PlatformSupport>,
890    
891    /// Feature usage analysis
892    pub feature_usage: FeatureUsage,
893    
894    /// Size analysis
895    pub size_analysis: SizeAnalysis,
896}
897
898/// Analysis configuration
899#[derive(Debug, Clone, Serialize, Deserialize)]
900pub struct AnalysisConfig {
901    /// Target platforms to analyze
902    pub target_platforms: Vec<String>,
903    
904    /// Check API compatibility
905    pub check_api_compatibility: bool,
906    
907    /// Check size constraints
908    pub check_size_constraints: bool,
909    
910    /// Check performance characteristics
911    pub check_performance: bool,
912    
913    /// Check safety requirements
914    pub check_security: bool,
915    
916    /// Strict mode (fail on any incompatibility)
917    pub strict_mode: bool,
918}
919
920/// Component information
921#[derive(Debug, Clone, Serialize, Deserialize)]
922pub struct ComponentInfo {
923    /// Component name
924    pub name: String,
925    
926    /// Component version
927    pub version: String,
928    
929    /// Component size in bytes
930    pub size: usize,
931    
932    /// Number of exports
933    pub exports_count: usize,
934    
935    /// Number of imports
936    pub imports_count: usize,
937    
938    /// Used features
939    pub features: HashSet<String>,
940}
941
942/// Compatibility issue
943#[derive(Debug, Clone, Serialize, Deserialize)]
944pub struct CompatibilityIssue {
945    /// Issue severity
946    pub severity: IssueSeverity,
947    
948    /// Issue category
949    pub category: IssueCategory,
950    
951    /// Affected platforms
952    pub affected_platforms: Vec<String>,
953    
954    /// Issue description
955    pub description: String,
956    
957    /// Suggested fix
958    pub fix_suggestion: Option<String>,
959}
960
961/// Issue severity levels
962#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
963pub enum IssueSeverity {
964    /// Informational
965    Info,
966    /// Warning
967    Warning,
968    /// Error (blocks deployment)
969    Error,
970    /// Critical (safety or major functionality issue)
971    Critical,
972}
973
974/// Issue categories
975#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
976pub enum IssueCategory {
977    /// API incompatibility
978    ApiIncompatibility,
979    /// Feature not supported
980    FeatureNotSupported,
981    /// Size constraint violation
982    SizeConstraint,
983    /// Performance concern
984    Performance,
985    /// Safety concern
986    Security,
987    /// Configuration issue
988    Configuration,
989}
990
991/// Recommendation for improving portability
992#[derive(Debug, Clone, Serialize, Deserialize)]
993pub struct Recommendation {
994    /// Recommendation priority
995    pub priority: RecommendationPriority,
996    
997    /// Recommendation title
998    pub title: String,
999    
1000    /// Detailed description
1001    pub description: String,
1002    
1003    /// Expected impact on portability score
1004    pub impact: f64,
1005    
1006    /// Affected platforms
1007    pub platforms: Vec<String>,
1008}
1009
1010impl fmt::Display for Recommendation {
1011    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1012        write!(f, "{}", self.title)
1013    }
1014}
1015
1016/// Recommendation priority levels
1017#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
1018pub enum RecommendationPriority {
1019    /// Low priority
1020    Low,
1021    /// Medium priority
1022    Medium,
1023    /// High priority
1024    High,
1025    /// Critical (must fix)
1026    Critical,
1027}
1028
1029/// Platform support information
1030#[derive(Debug, Clone, Serialize, Deserialize)]
1031pub struct PlatformSupport {
1032    /// Platform name
1033    pub platform: String,
1034    
1035    /// Support level
1036    pub support_level: SupportLevel,
1037    
1038    /// Compatibility score (0.0 - 1.0)
1039    pub compatibility_score: f64,
1040    
1041    /// Required modifications
1042    pub required_modifications: Vec<String>,
1043    
1044    /// Runtime version requirements
1045    pub runtime_requirements: Option<String>,
1046}
1047
1048/// Support levels for platforms
1049#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1050pub enum SupportLevel {
1051    /// Full support
1052    Full,
1053    /// Partial support (some features missing)
1054    Partial,
1055    /// Limited support (major limitations)
1056    Limited,
1057    /// No support
1058    None,
1059}
1060
1061/// Feature usage analysis
1062#[derive(Debug, Clone, Serialize, Deserialize)]
1063pub struct FeatureUsage {
1064    /// Core WASM features used
1065    pub core_features: HashSet<String>,
1066    
1067    /// Proposal features used
1068    pub proposal_features: HashSet<String>,
1069    
1070    /// Platform-specific features
1071    pub platform_specific: HashMap<String, HashSet<String>>,
1072    
1073    /// Feature compatibility matrix
1074    pub compatibility: HashMap<String, Vec<String>>,
1075}
1076
1077/// Size analysis for portability
1078#[derive(Debug, Clone, Serialize, Deserialize)]
1079pub struct SizeAnalysis {
1080    /// Total component size
1081    pub total_size: usize,
1082    
1083    /// Code size
1084    pub code_size: usize,
1085    
1086    /// Data size
1087    pub data_size: usize,
1088    
1089    /// Custom sections size
1090    pub custom_sections_size: usize,
1091    
1092    /// Size by section
1093    pub section_sizes: HashMap<String, usize>,
1094    
1095    /// Platform size limits
1096    pub platform_limits: HashMap<String, usize>,
1097}
1098
1099/// Platform requirements
1100#[derive(Debug, Clone)]
1101struct PlatformRequirements {
1102    /// Required features
1103    required_features: HashSet<String>,
1104    
1105    /// Optional features
1106    optional_features: HashSet<String>,
1107    
1108    /// Incompatible features
1109    incompatible_features: HashSet<String>,
1110    
1111    /// Size limit in bytes
1112    size_limit: Option<usize>,
1113    
1114    /// API requirements
1115    _api_requirements: HashSet<String>,
1116}
1117
1118/// Feature compatibility matrix
1119struct CompatibilityMatrix {
1120    /// Feature support by platform
1121    support: HashMap<String, HashMap<String, bool>>,
1122}
1123
1124impl Default for AnalysisConfig {
1125    fn default() -> Self {
1126        Self {
1127            target_platforms: vec![
1128                "cloudflare-workers".to_string(),
1129                "fastly-compute".to_string(),
1130                "aws-lambda".to_string(),
1131                "browser".to_string(),
1132                "nodejs".to_string(),
1133                "wasmtime".to_string(),
1134            ],
1135            check_api_compatibility: true,
1136            check_size_constraints: true,
1137            check_performance: true,
1138            check_security: true,
1139            strict_mode: false,
1140        }
1141    }
1142}
1143
1144impl Default for PortabilityAnalyzer {
1145    fn default() -> Self {
1146        Self::new()
1147    }
1148}
1149
1150impl PortabilityAnalyzer {
1151    /// Create a new portability analyzer with default config
1152    pub fn new() -> Self {
1153        Self {
1154            config: AnalysisConfig::default(),
1155            compatibility_matrix: Self::build_compatibility_matrix(),
1156            platform_requirements: Self::build_platform_requirements(),
1157        }
1158    }
1159    
1160    /// Create a new portability analyzer with specific config
1161    pub fn new_with_config(config: AnalysisConfig) -> Self {
1162        Self {
1163            config,
1164            compatibility_matrix: Self::build_compatibility_matrix(),
1165            platform_requirements: Self::build_platform_requirements(),
1166        }
1167    }
1168    
1169    /// Analyze a WASM component's portability
1170    pub fn analyze(&self, component: &WasmComponent) -> Result<PortabilityReport> {
1171        // Extract component information
1172        let component_info = self.extract_component_info(component)?;
1173        
1174        // Calculate portability scores
1175        let score = self.calculate_scores(&component_info)?;
1176        
1177        // Find compatibility issues
1178        let issues = self.find_issues(&component_info)?;
1179        
1180        // Generate recommendations
1181        let recommendations = self.generate_recommendations(&component_info, &issues)?;
1182        
1183        // Analyze platform support
1184        let platform_support = self.analyze_platform_support(&component_info)?;
1185        
1186        // Analyze feature usage
1187        let feature_usage = self.analyze_feature_usage(&component_info)?;
1188        
1189        // Analyze size
1190        let size_analysis = self.analyze_size(component)?;
1191        
1192        Ok(PortabilityReport {
1193            component_info,
1194            score,
1195            issues,
1196            recommendations,
1197            platform_support,
1198            feature_usage,
1199            size_analysis,
1200        })
1201    }
1202    
1203    fn extract_component_info(&self, component: &WasmComponent) -> Result<ComponentInfo> {
1204        let mut features = HashSet::new();
1205        
1206        // Analyze bytecode to detect used features
1207        // In a real implementation, this would parse the WASM module
1208        if component.bytecode.len() > 1024 * 100 {
1209            features.insert("large-module".to_string());
1210        }
1211        
1212        Ok(ComponentInfo {
1213            name: component.name.clone(),
1214            version: component.version.clone(),
1215            size: component.bytecode.len(),
1216            exports_count: component.exports.len(),
1217            imports_count: component.imports.len(),
1218            features,
1219        })
1220    }
1221    
1222    fn calculate_scores(&self, info: &ComponentInfo) -> Result<PortabilityScore> {
1223        let mut platform_scores = HashMap::new();
1224        
1225        // Calculate scores for each platform
1226        for platform in &self.config.target_platforms {
1227            let score = self.calculate_platform_score(info, platform)?;
1228            platform_scores.insert(platform.clone(), score);
1229        }
1230        
1231        // Calculate feature scores
1232        let feature_scores = self.calculate_feature_scores(info)?;
1233        
1234        // Calculate other scores
1235        let api_compatibility = self.calculate_api_compatibility(info)?;
1236        let size_efficiency = self.calculate_size_efficiency(info)?;
1237        let performance_portability = self.calculate_performance_portability(info)?;
1238        let security_compliance = self.calculate_security_compliance(info)?;
1239        
1240        // Calculate overall score
1241        let overall_score = Self::calculate_overall_score(
1242            &platform_scores,
1243            &feature_scores,
1244            api_compatibility,
1245            size_efficiency,
1246            performance_portability,
1247            security_compliance,
1248        );
1249        
1250        Ok(PortabilityScore {
1251            overall_score,
1252            platform_scores,
1253            feature_scores,
1254            api_compatibility,
1255            size_efficiency,
1256            performance_portability,
1257            security_compliance,
1258        })
1259    }
1260    
1261    fn calculate_platform_score(&self, info: &ComponentInfo, platform: &str) -> Result<f64> {
1262        let requirements = self.platform_requirements.get(platform);
1263        
1264        if let Some(reqs) = requirements {
1265            let mut score = 1.0;
1266            
1267            // Check size constraints
1268            if let Some(limit) = reqs.size_limit {
1269                if info.size > limit {
1270                    score *= 0.5; // Penalty for exceeding size limit
1271                }
1272            }
1273            
1274            // Check feature compatibility
1275            for feature in &info.features {
1276                if reqs.incompatible_features.contains(feature) {
1277                    score *= 0.0; // Incompatible feature
1278                } else if !reqs.required_features.contains(feature) && !reqs.optional_features.contains(feature) {
1279                    score *= 0.8; // Unknown feature
1280                }
1281            }
1282            
1283            Ok(score)
1284        } else {
1285            Ok(0.5) // Unknown platform
1286        }
1287    }
1288    
1289    fn calculate_feature_scores(&self, info: &ComponentInfo) -> Result<HashMap<String, f64>> {
1290        let mut scores = HashMap::new();
1291        
1292        // Score each feature based on platform support
1293        for feature in &info.features {
1294            let mut support_count = 0;
1295            let total_platforms = self.config.target_platforms.len();
1296            
1297            for platform in &self.config.target_platforms {
1298                if let Some(platform_features) = self.compatibility_matrix.support.get(platform) {
1299                    if platform_features.get(feature).copied().unwrap_or(false) {
1300                        support_count += 1;
1301                    }
1302                }
1303            }
1304            
1305            let score = f64::from(support_count) / total_platforms as f64;
1306            scores.insert(feature.clone(), score);
1307        }
1308        
1309        Ok(scores)
1310    }
1311    
1312    fn calculate_api_compatibility(&self, _info: &ComponentInfo) -> Result<f64> {
1313        // Check if APIs used are compatible across platforms
1314        // Simplified implementation
1315        Ok(0.9)
1316    }
1317    
1318    fn calculate_size_efficiency(&self, info: &ComponentInfo) -> Result<f64> {
1319        // Score based on component size
1320        let size_kb = info.size as f64 / 1024.0;
1321        
1322        if size_kb < 50.0 {
1323            Ok(1.0)
1324        } else if size_kb < 100.0 {
1325            Ok(0.9)
1326        } else if size_kb < 500.0 {
1327            Ok(0.7)
1328        } else if size_kb < 1000.0 {
1329            Ok(0.5)
1330        } else {
1331            Ok(0.3)
1332        }
1333    }
1334    
1335    fn calculate_performance_portability(&self, _info: &ComponentInfo) -> Result<f64> {
1336        // Analyze performance characteristics
1337        // Simplified implementation
1338        Ok(0.85)
1339    }
1340    
1341    fn calculate_security_compliance(&self, _info: &ComponentInfo) -> Result<f64> {
1342        // Check safety requirements
1343        // Simplified implementation
1344        Ok(0.95)
1345    }
1346    
1347    fn calculate_overall_score(
1348        platform_scores: &HashMap<String, f64>,
1349        feature_scores: &HashMap<String, f64>,
1350        api_compatibility: f64,
1351        size_efficiency: f64,
1352        performance_portability: f64,
1353        security_compliance: f64,
1354    ) -> f64 {
1355        let platform_avg = if platform_scores.is_empty() {
1356            0.0
1357        } else {
1358            platform_scores.values().sum::<f64>() / platform_scores.len() as f64
1359        };
1360        
1361        let feature_avg = if feature_scores.is_empty() {
1362            1.0
1363        } else {
1364            feature_scores.values().sum::<f64>() / feature_scores.len() as f64
1365        };
1366        
1367        // Weighted average
1368        platform_avg * 0.3 +
1369         feature_avg * 0.2 +
1370         api_compatibility * 0.2 +
1371         size_efficiency * 0.1 +
1372         performance_portability * 0.1 +
1373         security_compliance * 0.1
1374    }
1375    
1376    fn find_issues(&self, info: &ComponentInfo) -> Result<Vec<CompatibilityIssue>> {
1377        let mut issues = Vec::new();
1378        
1379        // Check size constraints
1380        for platform in &self.config.target_platforms {
1381            if let Some(reqs) = self.platform_requirements.get(platform) {
1382                if let Some(limit) = reqs.size_limit {
1383                    if info.size > limit {
1384                        issues.push(CompatibilityIssue {
1385                            severity: IssueSeverity::Warning,
1386                            category: IssueCategory::SizeConstraint,
1387                            affected_platforms: vec![platform.clone()],
1388                            description: format!(
1389                                "Component size ({} KB) exceeds {} platform limit ({} KB)",
1390                                info.size / 1024,
1391                                platform,
1392                                limit / 1024
1393                            ),
1394                            fix_suggestion: Some("Consider optimizing component size or splitting functionality".to_string()),
1395                        });
1396                    }
1397                }
1398            }
1399        }
1400        
1401        Ok(issues)
1402    }
1403    
1404    fn generate_recommendations(&self, info: &ComponentInfo, issues: &[CompatibilityIssue]) -> Result<Vec<Recommendation>> {
1405        let mut recommendations = Vec::new();
1406        
1407        // Size optimization recommendation
1408        if info.size > 100 * 1024 {
1409            recommendations.push(Recommendation {
1410                priority: RecommendationPriority::High,
1411                title: "Optimize component size".to_string(),
1412                description: "Component size can be reduced through optimization techniques".to_string(),
1413                impact: 0.2,
1414                platforms: self.config.target_platforms.clone(),
1415            });
1416        }
1417        
1418        // Feature compatibility recommendations
1419        for issue in issues {
1420            if issue.category == IssueCategory::FeatureNotSupported {
1421                recommendations.push(Recommendation {
1422                    priority: RecommendationPriority::Critical,
1423                    title: "Remove incompatible features".to_string(),
1424                    description: issue.description.clone(),
1425                    impact: 0.3,
1426                    platforms: issue.affected_platforms.clone(),
1427                });
1428            }
1429        }
1430        
1431        Ok(recommendations)
1432    }
1433    
1434    fn analyze_platform_support(&self, info: &ComponentInfo) -> Result<HashMap<String, PlatformSupport>> {
1435        let mut support = HashMap::new();
1436        
1437        for platform in &self.config.target_platforms {
1438            let score = self.calculate_platform_score(info, platform)?;
1439            
1440            let support_level = if score >= 0.9 {
1441                SupportLevel::Full
1442            } else if score >= 0.7 {
1443                SupportLevel::Partial
1444            } else if score >= 0.3 {
1445                SupportLevel::Limited
1446            } else {
1447                SupportLevel::None
1448            };
1449            
1450            support.insert(platform.clone(), PlatformSupport {
1451                platform: platform.clone(),
1452                support_level,
1453                compatibility_score: score,
1454                required_modifications: Vec::new(),
1455                runtime_requirements: None,
1456            });
1457        }
1458        
1459        Ok(support)
1460    }
1461    
1462    fn analyze_feature_usage(&self, info: &ComponentInfo) -> Result<FeatureUsage> {
1463        Ok(FeatureUsage {
1464            core_features: info.features.clone(),
1465            proposal_features: HashSet::new(),
1466            platform_specific: HashMap::new(),
1467            compatibility: HashMap::new(),
1468        })
1469    }
1470    
1471    fn analyze_size(&self, component: &WasmComponent) -> Result<SizeAnalysis> {
1472        let mut section_sizes = HashMap::new();
1473        
1474        // Add custom sections
1475        for (name, data) in &component.custom_sections {
1476            section_sizes.insert(name.clone(), data.len());
1477        }
1478        
1479        let custom_sections_size: usize = component.custom_sections.values().map(std::vec::Vec::len).sum();
1480        
1481        Ok(SizeAnalysis {
1482            total_size: component.bytecode.len(),
1483            code_size: component.bytecode.len() - custom_sections_size,
1484            data_size: 0,
1485            custom_sections_size,
1486            section_sizes,
1487            platform_limits: self.get_platform_limits(),
1488        })
1489    }
1490    
1491    fn get_platform_limits(&self) -> HashMap<String, usize> {
1492        let mut limits = HashMap::new();
1493        limits.insert("cloudflare-workers".to_string(), 10 * 1024 * 1024); // 10MB
1494        limits.insert("fastly-compute".to_string(), 50 * 1024 * 1024);    // 50MB
1495        limits.insert("aws-lambda".to_string(), 250 * 1024 * 1024);       // 250MB
1496        limits.insert("browser".to_string(), 100 * 1024 * 1024);          // 100MB
1497        limits
1498    }
1499    
1500    fn build_compatibility_matrix() -> CompatibilityMatrix {
1501        let mut support = HashMap::new();
1502        
1503        // Cloudflare Workers feature support
1504        let mut cloudflare = HashMap::new();
1505        cloudflare.insert("simd".to_string(), false);
1506        cloudflare.insert("threads".to_string(), false);
1507        cloudflare.insert("bulk-memory".to_string(), true);
1508        cloudflare.insert("reference-types".to_string(), true);
1509        support.insert("cloudflare-workers".to_string(), cloudflare);
1510        
1511        // Browser feature support
1512        let mut browser = HashMap::new();
1513        browser.insert("simd".to_string(), true);
1514        browser.insert("threads".to_string(), true);
1515        browser.insert("bulk-memory".to_string(), true);
1516        browser.insert("reference-types".to_string(), true);
1517        support.insert("browser".to_string(), browser);
1518        
1519        CompatibilityMatrix { support }
1520    }
1521    
1522    fn build_platform_requirements() -> HashMap<String, PlatformRequirements> {
1523        let mut requirements = HashMap::new();
1524        
1525        // Cloudflare Workers requirements
1526        requirements.insert("cloudflare-workers".to_string(), PlatformRequirements {
1527            required_features: HashSet::new(),
1528            optional_features: HashSet::from(["bulk-memory".to_string(), "reference-types".to_string()]),
1529            incompatible_features: HashSet::from(["threads".to_string()]),
1530            size_limit: Some(10 * 1024 * 1024),
1531            _api_requirements: HashSet::new(),
1532        });
1533        
1534        // Browser requirements
1535        requirements.insert("browser".to_string(), PlatformRequirements {
1536            required_features: HashSet::new(),
1537            optional_features: HashSet::from(["simd".to_string(), "threads".to_string()]),
1538            incompatible_features: HashSet::new(),
1539            size_limit: Some(100 * 1024 * 1024),
1540            _api_requirements: HashSet::new(),
1541        });
1542        
1543        requirements
1544    }
1545}