use dma_libfabric::{Configuration, Provider};
use dma_libfabric_protocol::{Advertisement, DmaError};
pub struct Arguments {
pub configuration: Configuration,
pub peer: Option<Advertisement>,
}
pub fn peer_from_stdin() -> Result<Advertisement, DmaError> {
let mut line = String::new();
std::io::stdin()
.read_line(&mut line)
.map_err(|error| DmaError::Fabric(format!("reading the advertisement: {error}")))?;
let fields: Vec<&str> = line.split_whitespace().collect();
match advertisement(&fields) {
Some(peer) => peer,
None => Err(DmaError::Fabric(format!(
"expected <address-hex> <rkey> <remote-addr>, got {} fields",
fields.len()
))),
}
}
fn advertisement(fields: &[&str]) -> Option<Result<Advertisement, DmaError>> {
let [address, remote_key, remote_address] = fields else {
return None;
};
Some(
Advertisement::from_fields(&[
address.as_bytes(),
remote_key.as_bytes(),
remote_address.as_bytes(),
])
.map_err(|error| DmaError::Fabric(error.to_string())),
)
}
pub fn parse() -> Result<Arguments, DmaError> {
let (flags, positional): (Vec<String>, Vec<String>) = std::env::args()
.skip(1)
.partition(|argument| argument.starts_with("--"));
let efa = flags.iter().any(|flag| "--efa" == flag);
let mut positional = positional.into_iter();
let configuration = Configuration {
providers: vec![if efa {
Provider::EfaDirect
} else {
Provider::Tcp
}],
bind: if efa { None } else { positional.next() },
..Configuration::default()
};
let fields: Vec<String> = positional.collect();
let fields: Vec<&str> = fields.iter().map(String::as_str).collect();
let peer = advertisement(&fields).transpose()?;
Ok(Arguments {
configuration,
peer,
})
}