typr_core/
abstractions.rs1use std::collections::HashMap;
7
8pub trait SourceProvider {
13 fn get_source(&self, path: &str) -> Option<String>;
15
16 fn exists(&self, path: &str) -> bool {
18 self.get_source(path).is_some()
19 }
20
21 fn list_sources(&self) -> Vec<String> {
23 vec![]
24 }
25}
26
27#[derive(Debug, Clone, Default)]
29pub struct InMemorySourceProvider {
30 sources: HashMap<String, String>,
31}
32
33impl InMemorySourceProvider {
34 pub fn new() -> Self {
36 Self {
37 sources: HashMap::new(),
38 }
39 }
40
41 pub fn add_source(&mut self, path: &str, content: &str) {
43 self.sources.insert(path.to_string(), content.to_string());
44 }
45
46 pub fn with_source(mut self, path: &str, content: &str) -> Self {
48 self.add_source(path, content);
49 self
50 }
51
52 pub fn remove_source(&mut self, path: &str) {
54 self.sources.remove(path);
55 }
56
57 pub fn clear(&mut self) {
59 self.sources.clear();
60 }
61}
62
63impl SourceProvider for InMemorySourceProvider {
64 fn get_source(&self, path: &str) -> Option<String> {
65 self.sources.get(path).cloned()
66 }
67
68 fn exists(&self, path: &str) -> bool {
69 self.sources.contains_key(path)
70 }
71
72 fn list_sources(&self) -> Vec<String> {
73 self.sources.keys().cloned().collect()
74 }
75}
76
77pub trait OutputHandler {
82 fn write_r_code(&mut self, filename: &str, content: &str) -> Result<(), OutputError>;
84
85 fn write_type_annotations(&mut self, filename: &str, content: &str) -> Result<(), OutputError>;
87
88 fn write_generic_functions(&mut self, filename: &str, content: &str)
90 -> Result<(), OutputError>;
91}
92
93#[derive(Debug, Clone, Default)]
95pub struct InMemoryOutputHandler {
96 pub outputs: HashMap<String, String>,
97}
98
99impl InMemoryOutputHandler {
100 pub fn new() -> Self {
101 Self {
102 outputs: HashMap::new(),
103 }
104 }
105
106 pub fn get_output(&self, filename: &str) -> Option<&String> {
107 self.outputs.get(filename)
108 }
109}
110
111impl OutputHandler for InMemoryOutputHandler {
112 fn write_r_code(&mut self, filename: &str, content: &str) -> Result<(), OutputError> {
113 self.outputs
114 .insert(filename.to_string(), content.to_string());
115 Ok(())
116 }
117
118 fn write_type_annotations(&mut self, filename: &str, content: &str) -> Result<(), OutputError> {
119 self.outputs
120 .insert(format!("{}_types", filename), content.to_string());
121 Ok(())
122 }
123
124 fn write_generic_functions(
125 &mut self,
126 filename: &str,
127 content: &str,
128 ) -> Result<(), OutputError> {
129 self.outputs
130 .insert(format!("{}_generics", filename), content.to_string());
131 Ok(())
132 }
133}
134
135#[derive(Debug, Clone)]
137pub struct OutputError {
138 pub message: String,
139}
140
141impl std::fmt::Display for OutputError {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 write!(f, "Output error: {}", self.message)
144 }
145}
146
147impl std::error::Error for OutputError {}
148
149pub trait PackageChecker {
154 fn is_package_available(&self, name: &str) -> bool;
156
157 fn install_package(&mut self, name: &str) -> Result<(), PackageError>;
159
160 fn get_package_types(&self, name: &str) -> Option<String>;
162}
163
164#[derive(Debug, Clone, Default)]
166pub struct StubPackageChecker {
167 available_packages: HashMap<String, String>,
168}
169
170impl StubPackageChecker {
171 pub fn new() -> Self {
172 Self {
173 available_packages: HashMap::new(),
174 }
175 }
176
177 pub fn register_package(&mut self, name: &str, types: &str) {
179 self.available_packages
180 .insert(name.to_string(), types.to_string());
181 }
182}
183
184impl PackageChecker for StubPackageChecker {
185 fn is_package_available(&self, name: &str) -> bool {
186 self.available_packages.contains_key(name)
187 }
188
189 fn install_package(&mut self, _name: &str) -> Result<(), PackageError> {
190 Ok(())
192 }
193
194 fn get_package_types(&self, name: &str) -> Option<String> {
195 self.available_packages.get(name).cloned()
196 }
197}
198
199#[derive(Debug, Clone)]
201pub struct PackageError {
202 pub message: String,
203}
204
205impl std::fmt::Display for PackageError {
206 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207 write!(f, "Package error: {}", self.message)
208 }
209}
210
211impl std::error::Error for PackageError {}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn test_in_memory_source_provider() {
219 let mut provider = InMemorySourceProvider::new();
220 provider.add_source("test.ty", "let x: Number = 42;");
221
222 assert!(provider.exists("test.ty"));
223 assert!(!provider.exists("nonexistent.ty"));
224 assert_eq!(
225 provider.get_source("test.ty"),
226 Some("let x: Number = 42;".to_string())
227 );
228 }
229
230 #[test]
231 fn test_builder_pattern() {
232 let provider = InMemorySourceProvider::new()
233 .with_source("a.ty", "let a = 1;")
234 .with_source("b.ty", "let b = 2;");
235
236 assert!(provider.exists("a.ty"));
237 assert!(provider.exists("b.ty"));
238 }
239}