1use std::path::PathBuf;
13
14#[derive(Debug, Clone)]
15pub struct CompilerConfig {
16 pub input_file: PathBuf,
17 pub output_file: Option<PathBuf>,
18 pub optimization_level: u8,
19 pub output_format: OutputFormat,
20 pub target_version: String,
21 pub include_debug_info: bool,
22 pub include_abi: bool,
23 pub include_source_map: bool,
24 pub gas_model: GasModel,
25 pub validate_only: bool,
26 pub analyze_only: bool,
27 pub verbose: bool,
28 pub warnings_as_errors: bool,
29 pub max_contract_size: usize,
30}
31
32#[derive(Debug, Clone, PartialEq)]
33pub enum OutputFormat {
34 Nef, Manifest, Complete, Assembly, Json, DebugInfo, }
41
42#[derive(Debug, Clone, PartialEq)]
43pub enum GasModel {
44 Ethereum,
45 Neo,
46 Hybrid,
47}
48
49impl Default for CompilerConfig {
50 fn default() -> Self {
51 Self {
52 input_file: PathBuf::new(),
53 output_file: None,
54 optimization_level: 2,
55 output_format: OutputFormat::Complete,
56 target_version: "3.0".to_string(),
57 include_debug_info: false,
58 include_abi: true,
59 include_source_map: false,
60 gas_model: GasModel::Neo,
61 validate_only: false,
62 analyze_only: false,
63 verbose: false,
64 warnings_as_errors: false,
65 max_contract_size: 512 * 1024,
66 }
67 }
68}
69
70impl CompilerConfig {
71 pub fn builder() -> CompilerConfigBuilder {
73 CompilerConfigBuilder::default()
74 }
75
76 pub fn validate(&self) -> Result<(), ConfigError> {
78 if self.optimization_level > 3 {
79 return Err(ConfigError::InvalidOptimizationLevel(
80 self.optimization_level,
81 ));
82 }
83 if self.input_file.as_os_str().is_empty() {
84 return Err(ConfigError::MissingInputFile);
85 }
86 Ok(())
87 }
88
89 pub fn is_debug_enabled(&self) -> bool {
91 self.include_debug_info || self.verbose
92 }
93
94 pub fn is_optimized(&self) -> bool {
96 self.optimization_level > 0
97 }
98
99 pub fn optimization_passes(&self) -> u32 {
101 match self.optimization_level {
102 0 => 0,
103 1 => 1,
104 2 => 2,
105 3 => 3,
106 _ => 2,
107 }
108 }
109}
110
111#[derive(Debug, Clone, Default)]
113pub struct CompilerConfigBuilder {
114 config: CompilerConfig,
115}
116
117impl CompilerConfigBuilder {
118 pub fn input_file(mut self, path: impl Into<PathBuf>) -> Self {
119 self.config.input_file = path.into();
120 self
121 }
122
123 pub fn output_file(mut self, path: impl Into<PathBuf>) -> Self {
124 self.config.output_file = Some(path.into());
125 self
126 }
127
128 pub fn optimization_level(mut self, level: u8) -> Self {
129 self.config.optimization_level = level;
130 self
131 }
132
133 pub fn output_format(mut self, format: OutputFormat) -> Self {
134 self.config.output_format = format;
135 self
136 }
137
138 pub fn target_version(mut self, version: impl Into<String>) -> Self {
139 self.config.target_version = version.into();
140 self
141 }
142
143 pub fn debug_info(mut self, enabled: bool) -> Self {
144 self.config.include_debug_info = enabled;
145 self
146 }
147
148 pub fn verbose(mut self, enabled: bool) -> Self {
149 self.config.verbose = enabled;
150 self
151 }
152
153 pub fn gas_model(mut self, model: GasModel) -> Self {
154 self.config.gas_model = model;
155 self
156 }
157
158 pub fn warnings_as_errors(mut self, enabled: bool) -> Self {
159 self.config.warnings_as_errors = enabled;
160 self
161 }
162
163 pub fn max_contract_size(mut self, size: usize) -> Self {
164 self.config.max_contract_size = size;
165 self
166 }
167
168 pub fn include_abi(mut self, enabled: bool) -> Self {
169 self.config.include_abi = enabled;
170 self
171 }
172
173 pub fn include_source_map(mut self, enabled: bool) -> Self {
174 self.config.include_source_map = enabled;
175 self
176 }
177
178 pub fn validate_only(mut self, enabled: bool) -> Self {
179 self.config.validate_only = enabled;
180 self
181 }
182
183 pub fn analyze_only(mut self, enabled: bool) -> Self {
184 self.config.analyze_only = enabled;
185 self
186 }
187
188 pub fn build(self) -> Result<CompilerConfig, ConfigError> {
190 self.config.validate()?;
191 Ok(self.config)
192 }
193
194 pub fn build_unchecked(self) -> CompilerConfig {
196 self.config
197 }
198}
199
200#[derive(Debug, Clone, PartialEq)]
202pub enum ConfigError {
203 MissingInputFile,
204 InvalidOptimizationLevel(u8),
205 InvalidTargetVersion(String),
206}
207
208impl std::fmt::Display for ConfigError {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 match self {
211 Self::MissingInputFile => write!(f, "input file is required"),
212 Self::InvalidOptimizationLevel(l) => {
213 write!(f, "optimization level {} is invalid (must be 0-3)", l)
214 }
215 Self::InvalidTargetVersion(v) => write!(f, "invalid target version: {}", v),
216 }
217 }
218}
219
220impl std::error::Error for ConfigError {}