Allow InputLocation::Stdin to specify a file name (#3265)

* Allow filename for InputLocation::StdIn

* clippy

* format code

* rename to input_file

* fix

* changes left out
This commit is contained in:
lazymio 2025-05-23 22:31:41 +08:00 committed by GitHub
parent 71d08f5f04
commit 18d46bed29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 9 deletions

View File

@ -164,7 +164,7 @@ where
} }
Ok(cmd.spawn()?) Ok(cmd.spawn()?)
} }
InputLocation::StdIn => { InputLocation::StdIn { input_file: _ } => {
let mut handle = self.command.stdin(Stdio::piped()).spawn()?; let mut handle = self.command.stdin(Stdio::piped()).spawn()?;
let mut stdin = handle.stdin.take().unwrap(); let mut stdin = handle.stdin.take().unwrap();
match stdin.write_all(input.target_bytes().as_slice()) { match stdin.write_all(input.target_bytes().as_slice()) {
@ -262,7 +262,7 @@ where
self.args[*argnum] = cstring_input; self.args[*argnum] = cstring_input;
} }
} }
InputLocation::StdIn => { InputLocation::StdIn { input_file: _ } => {
let (pipe_read, pipe_write) = pipe().unwrap(); let (pipe_read, pipe_write) = pipe().unwrap();
write(pipe_write, &input.target_bytes()).unwrap(); write(pipe_write, &input.target_bytes()).unwrap();
dup2(pipe_read.as_raw_fd(), STDIN_FILENO).unwrap(); dup2(pipe_read.as_raw_fd(), STDIN_FILENO).unwrap();
@ -590,7 +590,14 @@ impl CommandExecutorBuilder {
let mut command = Command::new(program); let mut command = Command::new(program);
match &self.target_inner.input_location { match &self.target_inner.input_location {
InputLocation::StdIn => { InputLocation::StdIn {
input_file: out_file,
} => {
if out_file.is_some() {
return Err(Error::illegal_argument(
"Setting filename for CommandExecutor is not supported!",
));
}
command.stdin(Stdio::piped()); command.stdin(Stdio::piped());
} }
InputLocation::File { .. } | InputLocation::Arg { .. } => { InputLocation::File { .. } | InputLocation::Arg { .. } => {

View File

@ -1031,7 +1031,12 @@ where
OT: ObserversTuple<I, S>, OT: ObserversTuple<I, S>,
{ {
let input_file = match &self.target_inner.input_location { let input_file = match &self.target_inner.input_location {
InputLocation::StdIn => InputFile::create(OsString::from(get_unique_std_input_file()))?, InputLocation::StdIn {
input_file: out_file,
} => match out_file {
Some(out_file) => out_file.clone(),
None => InputFile::create(OsString::from(get_unique_std_input_file()))?,
},
InputLocation::Arg { argnum: _ } => { InputLocation::Arg { argnum: _ } => {
return Err(Error::illegal_argument( return Err(Error::illegal_argument(
"forkserver doesn't support argument mutation", "forkserver doesn't support argument mutation",

View File

@ -11,7 +11,7 @@ use crate::fs::{InputFile, get_unique_std_input_file};
/// How to deliver input to an external program /// How to deliver input to an external program
/// `StdIn`: The target reads from stdin /// `StdIn`: The target reads from stdin
/// `File`: The target reads from the specified [`InputFile`] /// `File`: The target reads from the specified [`InputFile`]
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum InputLocation { pub enum InputLocation {
/// Mutate a commandline argument to deliver an input /// Mutate a commandline argument to deliver an input
Arg { Arg {
@ -19,8 +19,10 @@ pub enum InputLocation {
argnum: usize, argnum: usize,
}, },
/// Deliver input via `StdIn` /// Deliver input via `StdIn`
#[default] StdIn {
StdIn, /// The alternative input file
input_file: Option<InputFile>,
},
/// Deliver the input via the specified [`InputFile`] /// Deliver the input via the specified [`InputFile`]
/// You can use specify [`InputFile::create(INPUTFILE_STD)`] to use a default filename. /// You can use specify [`InputFile::create(INPUTFILE_STD)`] to use a default filename.
File { File {
@ -29,6 +31,12 @@ pub enum InputLocation {
}, },
} }
impl Default for InputLocation {
fn default() -> Self {
Self::StdIn { input_file: None }
}
}
/// The shared inner structs of trait [`StdTargetArgs`] /// The shared inner structs of trait [`StdTargetArgs`]
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct StdTargetArgsInner { pub struct StdTargetArgsInner {
@ -82,7 +90,10 @@ pub trait StdTargetArgs: Sized {
/// If use stdin /// If use stdin
#[must_use] #[must_use]
fn use_stdin(&self) -> bool { fn use_stdin(&self) -> bool {
matches!(self.inner().input_location, InputLocation::StdIn) matches!(
&self.inner().input_location,
InputLocation::StdIn { input_file: _ }
)
} }
/// Set input /// Set input
@ -114,7 +125,9 @@ pub trait StdTargetArgs: Sized {
assert!( assert!(
match &moved.inner().input_location { match &moved.inner().input_location {
InputLocation::File { out_file } => out_file.path.as_path() == path.as_ref(), InputLocation::File { out_file } => out_file.path.as_path() == path.as_ref(),
InputLocation::StdIn => true, InputLocation::StdIn { input_file } => input_file
.as_ref()
.is_none_or(|of| of.path.as_path() == path.as_ref()),
InputLocation::Arg { argnum: _ } => false, InputLocation::Arg { argnum: _ } => false,
}, },
"Already specified an input file under a different name. This is not supported" "Already specified an input file under a different name. This is not supported"