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
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
mod error;
pub mod format;
mod verif;

pub use error::GNVerifyError;
pub use format::Format;
use serde_json;
pub use std::io;
pub use verif::output::Output;
pub use verif::Input;
use verif::{remote, Verified};

#[derive(Debug, Default)]
pub struct GNVerify {
    sources: Option<Vec<i64>>,
    preferred_only: bool,
    pub format: Format,
}

impl GNVerify {
    pub fn new() -> Self {
        GNVerify {
            ..Default::default()
        }
    }

    pub fn sources(&mut self, sources: Vec<i64>) {
        self.sources = Some(sources);
    }

    pub fn preferred_only(&mut self) {
        self.preferred_only = true;
    }

    pub fn format(&mut self, format: Format) {
        self.format = format;
    }

    pub fn verify(&self, inputs: &Vec<Input>) -> Vec<Output> {
        let mut retries = 0;
        loop {
            match remote::verify(inputs, &self.sources) {
                Ok(resolved) => {
                    return self.process_outputs(resolved.name_resolver.responses, retries);
                }
                Err(err) => {
                    if retries < 3 {
                        retries += 1;
                    } else {
                        let error = Some(format!("{}", err));
                        return self.bad_outputs(inputs, retries, error);
                    }
                }
            };
        }
    }

    pub fn verify_and_format(&self, inputs: &Vec<Input>) {
        let outputs = self.verify(inputs);
        match self.format {
            Format::Pretty => self.write_json(outputs, true),
            Format::Compact => self.write_json(outputs, false),
            _ => self.write_csv(outputs).unwrap(),
        }
    }

    fn process_outputs(&self, results: Vec<Verified>, retries: i64) -> Vec<Output> {
        let mut outputs: Vec<Output> = Vec::with_capacity(results.len());
        for item in results {
            outputs.push(Output::new(item, retries, self.preferred_only))
        }
        outputs
    }

    fn bad_outputs(&self, inputs: &Vec<Input>, retries: i64, error: Option<String>) -> Vec<Output> {
        let mut outputs: Vec<Output> = Vec::with_capacity(inputs.len());
        for input in inputs {
            let output = Output {
                id: input.id.clone(),
                name: input.name.clone(),
                retries,
                error: error.clone(),
                ..Default::default()
            };
            outputs.push(output);
        }
        outputs
    }

    fn write_json(&self, outputs: Vec<Output>, pretty: bool) {
        for o in outputs {
            if pretty {
                print!("{}\n", serde_json::to_string_pretty(&o).unwrap());
            } else {
                print!("{}\n", serde_json::to_string(&o).unwrap());
            }
        }
    }

    fn write_csv(&self, outputs: Vec<Output>) -> anyhow::Result<()> {
        let mut wtr = csv::Writer::from_writer(io::stdout());
        for o in outputs {
            for c in o.to_csv(self.preferred_only) {
                wtr.serialize(c)?
            }
        }
        Ok(())
    }
}