mirror of
https://github.com/Noratrieb/cargo-minimize.git
synced 2026-01-14 08:25:01 +01:00
pass struct to code
This commit is contained in:
parent
159e8271fe
commit
bf8f13c62a
2 changed files with 70 additions and 20 deletions
|
|
@ -135,7 +135,7 @@ impl Build {
|
|||
});
|
||||
}
|
||||
|
||||
let (is_ice, output) = match &inner.mode {
|
||||
let (is_ice, cmd_status, output) = match &inner.mode {
|
||||
BuildMode::Cargo { subcommand } => {
|
||||
let mut cmd = self.cmd("cargo");
|
||||
|
||||
|
|
@ -158,6 +158,7 @@ impl Build {
|
|||
(
|
||||
// Cargo always exits with 101 when rustc has an error.
|
||||
output.contains("internal compiler error") || output.contains("' panicked at"),
|
||||
outputs.status,
|
||||
output,
|
||||
)
|
||||
}
|
||||
|
|
@ -183,6 +184,7 @@ impl Build {
|
|||
(
|
||||
outputs.status.code() == Some(101)
|
||||
|| output.contains("internal compiler error"),
|
||||
outputs.status,
|
||||
output,
|
||||
)
|
||||
}
|
||||
|
|
@ -201,14 +203,14 @@ impl Build {
|
|||
|
||||
let output = String::from_utf8(outputs.stderr)?;
|
||||
|
||||
(outputs.status.success(), output)
|
||||
(outputs.status.success(), outputs.status, output)
|
||||
}
|
||||
};
|
||||
|
||||
let reproduces_issue = match inner.verify {
|
||||
Verify::None => unreachable!("handled ealier"),
|
||||
Verify::Ice => is_ice,
|
||||
Verify::Custom(func) => func.call(&output),
|
||||
Verify::Custom(func) => func.call(&output, cmd_status.code()),
|
||||
};
|
||||
|
||||
Ok(BuildResult {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,15 @@ use std::{fmt::Debug, str::FromStr};
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
type CheckerCFn = unsafe extern "C" fn(*const u8, usize) -> bool;
|
||||
#[repr(C)]
|
||||
pub struct RawOutput {
|
||||
out_ptr: *const u8,
|
||||
out_len: usize,
|
||||
out_has_status: bool,
|
||||
out_status: i32,
|
||||
}
|
||||
|
||||
type CheckerCFn = unsafe extern "C" fn(*const RawOutput) -> bool;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RustFunction {
|
||||
|
|
@ -24,23 +32,50 @@ fn wrap_func_body(func: &str) -> Result<String> {
|
|||
let closure = syn::parse_str::<syn::ExprClosure>(func).context("invalid rust syntax")?;
|
||||
|
||||
let syn_file = syn::parse_quote! {
|
||||
#[repr(C)]
|
||||
pub struct __RawOutput {
|
||||
out_ptr: *const u8,
|
||||
out_len: usize,
|
||||
out_has_status: bool,
|
||||
out_status: i32,
|
||||
}
|
||||
|
||||
impl __RawOutput {
|
||||
unsafe fn as_output<'a>(&self) -> __Output<'a> {
|
||||
let slice = unsafe { std::slice::from_raw_parts(self.out_ptr, self.out_len) };
|
||||
let out = std::str::from_utf8(slice).unwrap();
|
||||
let status = self.out_has_status.then_some(self.out_status);
|
||||
__Output {
|
||||
out,
|
||||
status,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct __Output<'a> {
|
||||
out: &'a str,
|
||||
status: Option<i32>,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn cargo_minimize_ffi_function(ptr: *const u8, len: usize) -> bool {
|
||||
match std::panic::catch_unwind(|| __cargo_minimize_inner(ptr, len)) {
|
||||
pub unsafe extern "C" fn cargo_minimize_ffi_function(raw: *const __RawOutput) -> bool {
|
||||
match std::panic::catch_unwind(|| __cargo_minimize_inner(raw)) {
|
||||
Ok(bool) => bool,
|
||||
Err(_) => std::process::abort(),
|
||||
}
|
||||
}
|
||||
|
||||
fn __cargo_minimize_inner(__ptr: *const u8, __len: usize) -> bool {
|
||||
let __slice = unsafe { std::slice::from_raw_parts(__ptr, __len) };
|
||||
let __str = std::str::from_utf8(__slice).unwrap();
|
||||
#[allow(unused_parens)]
|
||||
unsafe fn __cargo_minimize_inner(__raw: *const __RawOutput) -> bool {
|
||||
let __output = __raw.read();
|
||||
let __output = __output.as_output();
|
||||
|
||||
fn ascribe_type<F: FnOnce(&str) -> bool>(f: F, output: &str) -> bool {
|
||||
fn ascribe_type<'a, F: FnOnce(__Output<'a>) -> bool>(f: F, output: __Output<'a>) -> bool {
|
||||
f(output)
|
||||
}
|
||||
|
||||
ascribe_type((#closure), __str)
|
||||
ascribe_type((#closure), __output)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -104,11 +139,22 @@ impl RustFunction {
|
|||
Ok(Self { func })
|
||||
}
|
||||
|
||||
pub fn call(&self, output: &str) -> bool {
|
||||
let ptr = output.as_ptr();
|
||||
let len = output.len();
|
||||
pub fn call(&self, output: &str, code: Option<i32>) -> bool {
|
||||
let out_ptr = output.as_ptr();
|
||||
let out_len = output.len();
|
||||
let (out_has_status, out_status) = match code {
|
||||
Some(status) => (true, status),
|
||||
None => (false, 0),
|
||||
};
|
||||
|
||||
unsafe { (self.func)(ptr, len) }
|
||||
let output = RawOutput {
|
||||
out_ptr,
|
||||
out_len,
|
||||
out_has_status,
|
||||
out_status,
|
||||
};
|
||||
|
||||
unsafe { (self.func)(&output) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,14 +171,16 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg_attr(not(target_os = "linux"), ignore)]
|
||||
fn basic_contains_work() {
|
||||
let code = r#"|output| output.contains("test")"#;
|
||||
let code = r#"|output| output.out.contains("test")"#;
|
||||
|
||||
let function = RustFunction::compile(code).unwrap();
|
||||
|
||||
let input = "this is a test";
|
||||
let not_input = "this is not a tst";
|
||||
let output = "this is a test";
|
||||
let not_output = "this is not a tst";
|
||||
|
||||
assert!(function.call(input));
|
||||
assert!(!function.call(not_input));
|
||||
let code = None;
|
||||
|
||||
assert!(function.call(output, code));
|
||||
assert!(!function.call(not_output, code));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue