Viaduct is a library for establishing a duplex communication channel between a parent and child process, using unnamed pipes.
```rs
pub enum ExampleRpc { Cow, Pig, Horse }
pub enum ExampleRequest { DoAFrontflip, DoABackflip, }
pub enum ExampleResponse { FrontflipOk, BackflipOk, } ```
```rs let child = std::process::Command::new("child.exe"); let ((tx, rx), mut child) = viaduct::ViaductBuilder::parent(child).unwrap();
std::thread::spawn(move || { rx.run( |rpc: ExampleRpc| match rpc { ExampleRpc::Cow => println!("Moo"), ExampleRpc::Pig => println!("Oink"), ExampleRpc::Horse => println!("Neigh"), },
|request: ExampleRequest| match request {
ExampleRequest::DoAFrontflip => {
println!("Doing a frontflip!");
ExampleResponse::FrontflipOk
},
ExampleRequest::DoABackflip => {
println!("Doing a backflip!");
ExampleResponse::BackflipOk
},
},
).unwrap();
});
tx.rpc(ExampleRpc::Cow).unwrap(); tx.rpc(ExampleRpc::Pig).unwrap(); tx.rpc(ExampleRpc::Horse).unwrap();
let response = tx.request(ExampleRequest::DoAFrontflip).unwrap(); assert_eq!(response, ExampleResponse::FrontflipOk); ```
```rs let (tx, rx) = viaduct::ViaductBuilder::child().unwrap();
std::thread::spawn(move || { rx.run( |rpc: ExampleRpc| match rpc { ExampleRpc::Cow => println!("Moo"), ExampleRpc::Pig => println!("Oink"), ExampleRpc::Horse => println!("Neigh"), },
|request: ExampleRequest| match request {
ExampleRequest::DoAFrontflip => {
println!("Doing a frontflip!");
ExampleResponse::FrontflipOk
},
ExampleRequest::DoABackflip => {
println!("Doing a backflip!");
ExampleResponse::BackflipOk
},
},
).unwrap();
});
tx.rpc(ExampleRpc::Horse).unwrap(); tx.rpc(ExampleRpc::Pig).unwrap(); tx.rpc(ExampleRpc::Cow).unwrap();
let response = tx.request(ExampleRequest::DoABackflip).unwrap(); assert_eq!(response, ExampleResponse::BackflipOk); ```
Viaduct was designed for separating user interface from application logic in a cross-platform manner.
For example, an application may want to run a GUI in a separate process from the application logic, for modularity or performance reasons.
Viaduct allows for applications like this to communicate between these processes in a natural way, without having to manually implement IPC machinery & synchronization.
Viaduct currently supports serialization and deserialization of data using bincode
or speedy
at your choice, using the respective Cargo feature flags.
You can also manually implement the [Pipeable
] trait.
A viaduct is initialized by calling [ViaductBuilder::parent
] as the parent process, which will spawn your child process.
Your child process should then call [ViaductBuilder::child
], [ViaductBuilder::child_with_args_os
], [ViaductBuilder::child_with_args
] (see CAVEAT below) to bridge the connection between the parent and child.
Then, you are ready to start...
Viaduct has two modes of operation: RPCs and Requests/Responses.
RPCs are one-way messages, and are useful for sending notifications to the other process.
Requests/Responses are two-way messages, and are useful for sending requests to the other process and receiving data as a response.
Requests will block any other thread trying to send requests and RPCs through the viaduct, until a response is received.
std::env::args_os
] or [std::env::args
] in your child process!The child process should not use args_os
or args
to get its arguments, as these will contain data Viaduct needs to pass to the child process.
Instead, use the argument iterator provided by [ViaductBuilder::child_with_args_os
] or [ViaductBuilder::child_with_args
] for args_os
and args
respectively.
Viaduct is licensed under the MIT license or the Apache License v2.0, at your choice.