1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::path::PathBuf;
6use thiserror::Error;
7use ::config::ConfigError;
8
9#[derive(Debug, Serialize, Deserialize, Clone)] #[serde(default)] pub struct Settings {
14 pub compiler_repository_url: String,
15 pub compiler_storage_path: Option<PathBuf>, pub installed_compilers: HashMap<String, CompilerInfo>,
17 pub file_associations: HashMap<String, String>, pub wine_path: Option<String>,
19}
20
21impl Default for Settings {
22 fn default() -> Self {
23 Settings {
24 compiler_repository_url: "https://raw.githubusercontent.com/RileyLeff/campbell-scientific-compilers/refs/heads/main/compilers.toml".to_string(),
26 compiler_storage_path: None, installed_compilers: HashMap::new(),
28 file_associations: HashMap::new(),
29 wine_path: None, }
31 }
32}
33
34#[derive(Debug, Serialize, Deserialize, Clone)]
39pub struct CompilerInfo {
40 pub id: String, pub description: String, pub version: String, pub install_subdir: PathBuf, pub executable_name: String, pub requires_wine: bool, pub supported_loggers: Option<Vec<String>>, }
49
50fn default_true() -> bool {
52 true
53}
54
55
56#[derive(Debug, Serialize, Deserialize, Clone)]
59pub struct Manifest {
60 pub manifest_version: String,
61 #[serde(default)] pub compilers: HashMap<String, ManifestCompilerEntry>, }
64
65#[derive(Debug, Serialize, Deserialize, Clone)]
66pub struct ManifestCompilerEntry {
67 pub description: String,
68 pub version: String,
69 pub download_url: String,
70 pub executable_name: String, #[serde(default = "default_true")] pub requires_wine: bool,
73 #[serde(default)]
74 pub supported_loggers: Option<Vec<String>>,
75 #[serde(default)]
76 pub sha256: Option<String>, }
78
79#[derive(Debug, Clone)] pub struct CompilationErrorDetail {
81 pub file_path_in_log: String, pub line: Option<u32>,
83 pub message: String,
84 }
86
87#[derive(Error, Debug)]
90pub enum Error {
91 #[error("Configuration error: {0}")]
92 Config(#[from] ConfigError),
93
94 #[error("I/O error: {0}")]
95 Io(#[from] std::io::Error),
96
97 #[error("Network error: {0}")]
98 Network(#[from] reqwest::Error),
99
100 #[error("Failed to process ZIP archive: {0}")]
101 Zip(#[from] zip::result::ZipError),
102
103 #[error("Compiler '{0}' not found in configuration.")]
107 CompilerNotFound(String),
108
109 #[error("SHA256 checksum mismatch for compiler '{compiler_id}'. Expected: '{expected}', Got: '{actual}'.")]
110 ChecksumMismatch { compiler_id: String,
112 expected: String,
113 actual: String,
114 },
115
116 #[error("No compiler associated with file extension '.{0}'. Please configure an association.")]
117 NoCompilerForExtension(String),
118
119 #[error("Could not find Wine executable. Please install Wine or set the path in configuration.")]
120 WineNotFound,
121
122 #[error("Failed to execute subprocess: {0}")]
123 Subprocess(std::io::Error), #[error("Compilation of '{file_path}' failed.")]
126 CompilationFailed {
127 file_path: PathBuf, errors: Vec<CompilationErrorDetail>,
129 raw_log: String, },
131
132 #[error("Compiler reported failure for '{file_path}'. Log:\n{raw_log}")]
134 GenericCompilationFailedWithLog {
135 file_path: PathBuf,
136 raw_log: String,
137 },
138
139 #[error("Compiler execution failed. Output Log:\n{log_content}")]
140 CompilationFailedWithLog { log_content: String }, #[error("Invalid compiler source or manifest: {0}")]
143 InvalidCompilerSource(String),
144
145 #[error("Failed to determine application directories.")]
146 DirectoryResolutionFailed,
147
148 #[error("Compiler ID '{0}' not found in the repository manifest.")]
149 CompilerIdNotFoundInManifest(String),
150
151 #[error("Invalid file extension: '{0}'.")]
152 InvalidExtension(String),
153}
154
155pub mod config;
157pub mod compiler;
158pub mod installer;
159pub fn compile_file(
163 input_file: PathBuf,
164 output_log: Option<PathBuf>,
165 compiler_id: Option<String>,
166 settings: &Settings,
167) -> Result<(), Error> {
168 compiler::compile_file_impl(
169 &input_file,
170 output_log.as_deref(), compiler_id.as_deref(), settings,
173 )
174}
175
176
177#[cfg(test)]
178mod tests {
179 }