use std::collections::BTreeMap;
use std::ops::ControlFlow;
use std::time::Duration;
use clap::Args;
use crate::input::InputArgs;
use crate::json;
use crate::print::{or_unknown, print_service};
use crate::si::{self, Network, Services, Si};
#[derive(Clone, Debug, Args)]
pub struct Options {
#[command(flatten)]
input: InputArgs,
#[arg(long, default_value_t = 30)]
timeout: u64,
#[arg(long)]
json: bool,
}
pub fn run(options: &Options) -> anyhow::Result<()> {
let mut network: Option<Network> = None;
let mut streams = BTreeMap::<(u16, u16), Services>::new();
si::read(
options.input.open()?,
Duration::from_secs(options.timeout),
|si| {
match si {
Si::Network(found) => network = Some(found),
Si::Services(services) => {
streams.insert((services.original_network_id, services.stream_id), services);
}
Si::Events(_) | Si::Streams(_) => {}
}
ControlFlow::Continue(())
},
)?;
if options.json {
let streams: Vec<_> = streams
.values()
.map(|services| {
serde_json::json!({
"id": services.stream_id,
"original_network_id": services.original_network_id,
"actual": services.actual,
"services": services.services.iter().map(json::service).collect::<Vec<_>>(),
})
})
.collect();
println!(
"{}",
serde_json::json!({
"network": network.as_ref().map(json::network),
"streams": streams,
})
);
return Ok(());
}
if let Some(network) = &network {
println!("Network: {:#06X} {}", network.id, or_unknown(&network.name));
}
for ((original_network_id, stream_id), services) in &streams {
let actual = if services.actual {
" (this stream)"
} else {
""
};
println!("Stream: {stream_id:#06X} of network {original_network_id:#06X}{actual}");
for service in &services.services {
print_service(service, 2);
}
}
for stream in network.iter().flat_map(|network| &network.streams) {
if !streams.contains_key(&(stream.original_network_id, stream.id)) {
println!(
"Stream: {:#06X} of network {:#06X} (services not found)",
stream.id, stream.original_network_id
);
for service_id in &stream.service_ids {
println!(" {service_id:#06X}");
}
}
}
Ok(())
}