subprocess.rs 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. use super::{Open, Sink};
  2. use shell_words::split;
  3. use std::io::{self, Write};
  4. use std::mem;
  5. use std::process::{Child, Command, Stdio};
  6. use std::slice;
  7. pub struct SubprocessSink {
  8. shell_command: String,
  9. child: Option<Child>,
  10. }
  11. impl Open for SubprocessSink {
  12. fn open(shell_command: Option<String>) -> SubprocessSink {
  13. if let Some(shell_command) = shell_command {
  14. SubprocessSink {
  15. shell_command: shell_command,
  16. child: None,
  17. }
  18. } else {
  19. panic!("subprocess sink requires specifying a shell command");
  20. }
  21. }
  22. }
  23. impl Sink for SubprocessSink {
  24. fn start(&mut self) -> io::Result<()> {
  25. let args = split(&self.shell_command).unwrap();
  26. self.child = Some(
  27. Command::new(&args[0])
  28. .args(&args[1..])
  29. .stdin(Stdio::piped())
  30. .spawn()?,
  31. );
  32. Ok(())
  33. }
  34. fn stop(&mut self) -> io::Result<()> {
  35. if let Some(child) = &mut self.child.take() {
  36. child.kill()?;
  37. child.wait()?;
  38. }
  39. Ok(())
  40. }
  41. fn write(&mut self, data: &[i16]) -> io::Result<()> {
  42. let data: &[u8] = unsafe {
  43. slice::from_raw_parts(
  44. data.as_ptr() as *const u8,
  45. data.len() * mem::size_of::<i16>(),
  46. )
  47. };
  48. if let Some(child) = &mut self.child {
  49. let child_stdin = child.stdin.as_mut().unwrap();
  50. child_stdin.write_all(data)?;
  51. }
  52. Ok(())
  53. }
  54. }