Skip to main content

typr_core/
abstractions.rs

1//! Abstraction traits for platform-independent operations
2//!
3//! These traits allow typr-core to work both natively (with filesystem access)
4//! and in WebAssembly (with in-memory sources).
5
6use std::collections::HashMap;
7
8/// Provides source code content for compilation.
9///
10/// This trait abstracts away file system access, allowing the compiler
11/// to work with in-memory sources (useful for WASM and testing).
12pub trait SourceProvider {
13    /// Get the source code for a given file path
14    fn get_source(&self, path: &str) -> Option<String>;
15
16    /// Check if a source file exists
17    fn exists(&self, path: &str) -> bool {
18        self.get_source(path).is_some()
19    }
20
21    /// List available source files (for module resolution)
22    fn list_sources(&self) -> Vec<String> {
23        vec![]
24    }
25}
26
27/// In-memory source provider for WASM and testing
28#[derive(Debug, Clone, Default)]
29pub struct InMemorySourceProvider {
30    sources: HashMap<String, String>,
31}
32
33impl InMemorySourceProvider {
34    /// Create a new empty source provider
35    pub fn new() -> Self {
36        Self {
37            sources: HashMap::new(),
38        }
39    }
40
41    /// Add a source file
42    pub fn add_source(&mut self, path: &str, content: &str) {
43        self.sources.insert(path.to_string(), content.to_string());
44    }
45
46    /// Add a source file (builder pattern)
47    pub fn with_source(mut self, path: &str, content: &str) -> Self {
48        self.add_source(path, content);
49        self
50    }
51}
52
53impl SourceProvider for InMemorySourceProvider {
54    fn get_source(&self, path: &str) -> Option<String> {
55        self.sources.get(path).cloned()
56    }
57
58    fn exists(&self, path: &str) -> bool {
59        self.sources.contains_key(path)
60    }
61
62    fn list_sources(&self) -> Vec<String> {
63        self.sources.keys().cloned().collect()
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_in_memory_source_provider() {
73        let mut provider = InMemorySourceProvider::new();
74        provider.add_source("test.ty", "let x: Number = 42;");
75
76        assert!(provider.exists("test.ty"));
77        assert!(!provider.exists("nonexistent.ty"));
78        assert_eq!(
79            provider.get_source("test.ty"),
80            Some("let x: Number = 42;".to_string())
81        );
82    }
83
84    #[test]
85    fn test_builder_pattern() {
86        let provider = InMemorySourceProvider::new()
87            .with_source("a.ty", "let a = 1;")
88            .with_source("b.ty", "let b = 2;");
89
90        assert!(provider.exists("a.ty"));
91        assert!(provider.exists("b.ty"));
92    }
93}