pub trait Input: Sized {
    fn configure(self, config: &mut Config);

    fn run(self) { ... }
    fn run_output<O>(self) -> O
    where
        O: Output
, { ... } fn run_result<O>(self) -> Result<O, Error>
    where
        O: Output
, { ... } }
Expand description

All types that are possible arguments to run!, run_output! or run_result! must implement this trait. This makes cradle very flexible. For example you can pass in an executable as a String, and a variable number of arguments as a Vec:

use cradle::prelude::*;

let executable = "echo";
let arguments = vec!["foo", "bar"];
let StdoutUntrimmed(output) = run_output!(executable, arguments);
assert_eq!(output, "foo bar\n");

For more documentation on all possible input types, see the documentation for the individual impls of Input. Here’s a non-exhaustive list of the most commonly used types to get you started:

Tuples

cradle also implements Input for tuples of types that themselves implement Input. Instead of passing multiple arguments to run!, they can be passed in a single tuple:

use cradle::prelude::*;

let args = ("echo", "foo");
let StdoutTrimmed(output) = run_output!(args);
assert_eq!(output, "foo");

This can be used to group arguments:

use cradle::prelude::*;

let to_hex_command = ("xxd", "-ps", "-u", LogCommand);
let StdoutTrimmed(output) = run_output!(to_hex_command, Stdin(&[14, 15, 16]));
assert_eq!(output, "0E0F10");

Also, tuples make it possible to write wrappers around run! without requiring the use of macros:

use cradle::prelude::*;

fn to_hex<I: Input>(input: I) -> String {
  let StdoutTrimmed(hex) = run_output!(%"xxd -ps -u", input);
  hex
}

// It works for slices:
let hex = to_hex(Stdin(&[14, 15, 16]));
assert_eq!(hex, "0E0F10");

// Vectors:
let hex = to_hex(Stdin(vec![14, 15, 16]));
assert_eq!(hex, "0E0F10");

// And multiple arguments using tuples:
let hex = to_hex((Stdin(&[14, 15, 16]), Stdin(&[17, 18, 19])));
assert_eq!(hex, "0E0F10111213");

Custom Input impls

The provided Input implementations should be sufficient for most use cases, but custom Input implementations can be written to extend cradle.

Here’s an example of an Environment type, that wraps BTreeMap and adds all contained key-value pairs to the environment of the child process.

use cradle::prelude::*;
use cradle::config::Config;
use std::collections::BTreeMap;

struct Environment(BTreeMap<String, String>);

impl Environment {
    fn new() -> Self {
        Environment(BTreeMap::new())
    }

    fn add(mut self, key: &str, value: &str) -> Self {
        self.0.insert(key.to_owned(), value.to_owned());
        self
    }
}

impl Input for Environment {
    fn configure(self, config: &mut Config) {
        for (key, value) in self.0.into_iter() {
            Env(key, value).configure(config)
        }
    }
}

let env_vars = Environment::new()
    .add("FOO", "foo")
    .add("BAR", "bar");

let StdoutUntrimmed(output) = run_output!("env", env_vars);
assert!(output.contains("FOO=foo\n"));
assert!(output.contains("BAR=bar\n"));

It is not recommended to override run, run_output or run_result.

Also note that all fields of the type Config are private. That means that when you’re writing your own Input impls, you have to implement the Input::configure method of your type in terms of the Input::configure methods of the various Input types that cradle provides – as demonstrated in the code snippet above. Config’s fields are private to allow to add new features to cradle without introducing breaking API changes.

Required Methods

Configures the given Config for the Input self. Usually you won’t have to write your own custom impls for Input, nor call this function yourself. So you can safely ignore this method.

See also Custom Input impls.

Provided Methods

input.run() runs input as a child process. It’s equivalent to run!(input).

use cradle::prelude::*;

("touch", "foo").run();

input.run() runs input as a child process. It’s equivalent to run_output!(input).

use cradle::prelude::*;

let StdoutTrimmed(output) = ("echo", "foo").run_output();
assert_eq!(output, "foo");

input.run_result() runs input as a child process. It’s equivalent to run_result!(input).

use cradle::prelude::*;

// make sure build tools are installed
run_result!(%"which make")?;
run_result!(%"which gcc")?;
run_result!(%"which ld")?;
run_result!(%"make build")?;

Implementations on Foreign Types

Blanket implementation for &_.

Arguments of type OsString are passed to the child process as arguments.

use cradle::prelude::*;

run!("ls", std::env::var_os("HOME").unwrap());

Arguments of type &OsStr are passed to the child process as arguments.

use cradle::prelude::*;

run!("echo", std::env::current_dir().unwrap().file_name().unwrap());

Arguments of type &str are passed to the child process as arguments. This is especially useful because it allows you to use string literals:

use cradle::prelude::*;

let StdoutTrimmed(output) = run_output!("echo", "foo");
assert_eq!(output, "foo");

Arguments of type String are passed to the child process as arguments. Executables can also be passed as Strings:

use cradle::prelude::*;

let executable: String = "echo".to_string();
let argument: String = "foo".to_string();
let StdoutTrimmed(output) = run_output!(executable, argument);
assert_eq!(output, "foo");

Allows to use split to split your argument into words:

use cradle::prelude::*;

let StdoutTrimmed(output) = run_output!("echo foo".split(' '));
assert_eq!(output, "foo");

Arguments to split must be of type char.

Allows to use split_whitespace to split your argument into words:

use cradle::prelude::*;

let StdoutTrimmed(output) = run_output!("echo foo".split_whitespace());
assert_eq!(output, "foo");

Allows to use split_ascii_whitespace to split your argument into words:

use cradle::prelude::*;

let StdoutTrimmed(output) = run_output!("echo foo".split_ascii_whitespace());
assert_eq!(output, "foo");

All elements of the given Vec are used as arguments to the child process. Same as passing in the elements separately.

use cradle::prelude::*;

let StdoutTrimmed(output) = run_output!(vec!["echo", "foo"]);
assert_eq!(output, "foo");

Similar to the implementation for Vec<T>. All elements of the array will be used as arguments.

use cradle::prelude::*;

let StdoutTrimmed(output) = run_output!(["echo", "foo"]);
assert_eq!(output, "foo");

Only works on rust version 1.51 and up.

Similar to the implementation for Vec<T>. All elements of the slice will be used as arguments.

Arguments of type PathBuf are passed to the child process as arguments.

use cradle::prelude::*;
use std::path::PathBuf;

let current_dir: PathBuf = std::env::current_dir().unwrap();
run!("ls", current_dir);

Arguments of type &Path are passed to the child process as arguments.

use cradle::prelude::*;
use std::path::Path;

let file: &Path = Path::new("./foo");
run!("touch", file);

Implementors