summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: feb6e9c9523a571b889278f0503ac58e8fd59699 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
mod protos;
use protos::protos::gtfs_realtime::FeedMessage;

use protobuf::Message;
use clap::Parser;
// use anyhow::Context;
use miette::{WrapErr, IntoDiagnostic, miette};
use reqwest::header::{HeaderValue, CONTENT_TYPE};

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
   /// uri of the GTFS RT feed to fetch & display
   url: String,
   /// emit the feed as json
   #[arg(long)]
   json: bool,
   #[arg(long="ignore-nonfatal", short='i')]
   ignore_nonfatal: bool
}


#[tokio::main]
async fn main() -> miette::Result<()> {

    let args = Args::parse();
    let resp = reqwest::get(&args.url)
        .await.into_diagnostic().wrap_err("Request failed")?
        .error_for_status().into_diagnostic()?;

    if !args.ignore_nonfatal {
        let ct = HeaderValue::from_static("application/octet-stream");
        match resp.headers().get(CONTENT_TYPE) {
            Some(content_type) if ct == content_type => (),
            Some(other_type) =>
                Err(miette!("should be {:?}", ct))
                  .wrap_err(format!("Bad Content-Type {:?}", other_type))?,
            None =>
                Err(miette!("Content-Type header is missing"))?
        }
    }

    let resp = resp
        .bytes().await.into_diagnostic()?;

    let proto = FeedMessage::parse_from_bytes(&resp[..])
        .into_diagnostic()
        .wrap_err("Could not parse protobuf format")?;

    match args.json {
        true => 
            println!("{}", protobuf_json_mapping::print_to_string(&proto).into_diagnostic()?),
        false => 
            println!("{}", protobuf::text_format::print_to_string_pretty(&proto))
    }
    Ok(())
}