Skip to content

Instantly share code, notes, and snippets.

@josephg
Created September 17, 2024 07:48
Show Gist options
  • Save josephg/71e121b0f85489dea0b2e8cda5ec77fa to your computer and use it in GitHub Desktop.
Save josephg/71e121b0f85489dea0b2e8cda5ec77fa to your computer and use it in GitHub Desktop.
shell out from rust to another program
/// Calls `dot -Tsvg` and passes in the contents of dot_content via stdin.
///
/// The output is read back to a string and returned.
pub fn generate_svg_with_dot(dot_content: String, dot_path: Option<OsString>) -> Result<String, Box<dyn Error>> {
let dot_path = dot_path.unwrap_or_else(|| "dot".into());
let mut child = Command::new(dot_path)
// .arg("-Tpng")
.arg("-Tsvg")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
let mut stdin = child.stdin.take().unwrap();
// Spawn is needed here to prevent a potential deadlock. See:
// https://doc.rust-lang.org/std/process/index.html#handling-io
std::thread::spawn(move || {
stdin.write_all(dot_content.as_bytes()).unwrap();
});
let out = child.wait_with_output()?;
// Pipe stderr.
std::io::stderr().write_all(&out.stderr)?;
if out.status.success() {
Ok(String::from_utf8(out.stdout)?)
} else {
// May as well pipe stdout too.
std::io::stdout().write_all(&out.stdout)?;
Err(DotError.into())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment