neo_solidity/
types.rs

1//! Compiler Configuration Types
2//!
3//! This module defines configuration structures for the Neo Solidity compiler,
4//! including input/output settings, optimization levels, and output formats.
5//!
6//! # Key Types
7//!
8//! - [`CompilerConfig`] - Main configuration for compilation
9//! - [`OutputFormat`] - Supported output formats (NEF, JSON, etc.)
10//! - [`GasModel`] - Gas calculation model selection
11
12use 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,       // Neo Executable Format (.nef)
35    Manifest,  // Neo Manifest (.manifest.json)
36    Complete,  // Both .nef and .manifest.json
37    Assembly,  // Human-readable assembly
38    Json,      // Complete JSON with all outputs
39    DebugInfo, // Debug information
40}
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    /// Create a new builder for CompilerConfig
72    pub fn builder() -> CompilerConfigBuilder {
73        CompilerConfigBuilder::default()
74    }
75
76    /// Validate the configuration
77    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    /// Check if debug output is enabled
90    pub fn is_debug_enabled(&self) -> bool {
91        self.include_debug_info || self.verbose
92    }
93
94    /// Check if optimization is enabled
95    pub fn is_optimized(&self) -> bool {
96        self.optimization_level > 0
97    }
98
99    /// Get optimization passes based on level
100    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/// Builder for CompilerConfig with fluent API
112#[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    /// Build and validate the configuration
189    pub fn build(self) -> Result<CompilerConfig, ConfigError> {
190        self.config.validate()?;
191        Ok(self.config)
192    }
193
194    /// Build without validation (for testing)
195    pub fn build_unchecked(self) -> CompilerConfig {
196        self.config
197    }
198}
199
200/// Configuration validation errors
201#[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 {}