mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 15:41:04 +00:00
497dae2494
The differential testing framework will make a second consumer. There seems to be no re-usable Rust crate for this. But we already have everything here, just needs a small refactor to make it fully re-usable. - Mostly decouple the solc JSON-input-output interface types from the `solidity` frontend crate - Expose the JSON-input-output interface types in a dedicated crate --------- Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
122 lines
4.2 KiB
Rust
122 lines
4.2 KiB
Rust
//! The Solidity compiler solJson interface.
|
|
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
|
|
use revive_solc_json_interface::combined_json::CombinedJson;
|
|
use revive_solc_json_interface::SolcStandardJsonInput;
|
|
use revive_solc_json_interface::SolcStandardJsonOutput;
|
|
|
|
use crate::solc::version::Version;
|
|
use anyhow::Context;
|
|
use std::ffi::{c_char, c_void, CStr, CString};
|
|
|
|
use super::Compiler;
|
|
|
|
extern "C" {
|
|
fn soljson_version() -> *const c_char;
|
|
fn soljson_compile(inputPtr: *const c_char, inputLen: usize) -> *const c_char;
|
|
}
|
|
|
|
/// The Solidity compiler.
|
|
pub struct SoljsonCompiler;
|
|
|
|
impl Compiler for SoljsonCompiler {
|
|
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
|
fn standard_json(
|
|
&mut self,
|
|
mut input: SolcStandardJsonInput,
|
|
base_path: Option<String>,
|
|
include_paths: Vec<String>,
|
|
allow_paths: Option<String>,
|
|
) -> anyhow::Result<SolcStandardJsonOutput> {
|
|
if !include_paths.is_empty() {
|
|
anyhow::bail!("configuring include paths is not supported with solJson")
|
|
}
|
|
if base_path.is_some() {
|
|
anyhow::bail!("configuring the base path is not supported with solJson")
|
|
}
|
|
if allow_paths.is_some() {
|
|
anyhow::bail!("configuring allow paths is not supported with solJson")
|
|
}
|
|
|
|
let version = self.version()?.validate(&include_paths)?.default;
|
|
input.normalize(&version);
|
|
|
|
let suppressed_warnings = input.suppressed_warnings.take().unwrap_or_default();
|
|
|
|
let input_json = serde_json::to_string(&input).expect("Always valid");
|
|
let out = Self::compile_standard_json(input_json)?;
|
|
let mut output: SolcStandardJsonOutput =
|
|
revive_common::deserialize_from_slice(out.as_bytes()).map_err(|error| {
|
|
anyhow::anyhow!(
|
|
"Soljson output parsing error: {}\n{}",
|
|
error,
|
|
revive_common::deserialize_from_slice::<serde_json::Value>(out.as_bytes())
|
|
.map(|json| serde_json::to_string_pretty(&json).expect("Always valid"))
|
|
.unwrap_or_else(|_| String::from_utf8_lossy(out.as_bytes()).to_string()),
|
|
)
|
|
})?;
|
|
output.preprocess_ast(suppressed_warnings.as_slice())?;
|
|
|
|
Ok(output)
|
|
}
|
|
|
|
fn combined_json(
|
|
&self,
|
|
_paths: &[PathBuf],
|
|
_combined_json_argument: &str,
|
|
) -> anyhow::Result<CombinedJson> {
|
|
unimplemented!();
|
|
}
|
|
|
|
fn validate_yul(&self, _path: &Path) -> anyhow::Result<()> {
|
|
unimplemented!();
|
|
}
|
|
|
|
fn version(&mut self) -> anyhow::Result<Version> {
|
|
let version = Self::get_soljson_version()?;
|
|
let long = version.clone();
|
|
let default: semver::Version = version
|
|
.split('+')
|
|
.next()
|
|
.ok_or_else(|| anyhow::anyhow!("Soljson version parsing: metadata dropping"))?
|
|
.parse()
|
|
.map_err(|error| anyhow::anyhow!("Soljson version parsing: {}", error))?;
|
|
let l2_revision: Option<semver::Version> = version
|
|
.split('-')
|
|
.nth(1)
|
|
.and_then(|version| version.parse().ok());
|
|
Ok(Version::new(long, default, l2_revision))
|
|
}
|
|
}
|
|
|
|
impl SoljsonCompiler {
|
|
fn get_soljson_version() -> anyhow::Result<String> {
|
|
unsafe {
|
|
let version_ptr = soljson_version();
|
|
let version = CStr::from_ptr(version_ptr)
|
|
.to_str()
|
|
.with_context(|| "Failed to convert C string to Rust string")
|
|
.map(str::to_owned);
|
|
libc::free(version_ptr as *mut c_void);
|
|
Ok(version?)
|
|
}
|
|
}
|
|
|
|
fn compile_standard_json(input: String) -> anyhow::Result<String> {
|
|
let c_input = CString::new(input).unwrap();
|
|
let c_input_len = c_input.as_bytes().len();
|
|
|
|
unsafe {
|
|
let output_ptr = soljson_compile(c_input.as_ptr(), c_input_len);
|
|
let output_json = CStr::from_ptr(output_ptr)
|
|
.to_str()
|
|
.with_context(|| "Failed to convert C string to Rust string")
|
|
.map(str::to_owned);
|
|
libc::free(output_ptr as *mut c_void);
|
|
Ok(output_json?)
|
|
}
|
|
}
|
|
}
|