bookdata/cli/
openlib.rs

1use std::path::{Path, PathBuf};
2
3use serde::de::DeserializeOwned;
4
5use crate::io::LineProcessor;
6use crate::openlib::*;
7use crate::prelude::*;
8use crate::util::logging::data_progress;
9
10use super::Command;
11
12#[derive(Args, Debug)]
13struct Input {
14    /// Input file
15    #[arg(name = "INPUT")]
16    infile: PathBuf,
17}
18
19#[derive(clap::Subcommand, Debug)]
20enum DataType {
21    /// Parse OpenLibrary works.
22    ///
23    /// Authors must be processed first.
24    ScanWorks(Input),
25
26    /// Parse OpenLibrary editions.
27    ///
28    /// Authors and works must be processed first.
29    ScanEditions(Input),
30
31    /// Parse OpenLibrary authors.
32    ScanAuthors(Input),
33}
34
35/// Scan OpenLibrary data.
36#[derive(Args, Debug)]
37#[command(name = "openlib")]
38pub struct OpenLib {
39    #[command(subcommand)]
40    mode: DataType,
41}
42
43/// Helper function to route OpenLibrary data.
44fn scan_openlib<R, Proc>(path: &Path, proc: Proc) -> Result<()>
45where
46    Proc: ObjectWriter<Row<R>>,
47    R: DeserializeOwned,
48{
49    let mut proc = proc;
50    let mut nlines = 0;
51    info!("opening file {}", path.to_string_lossy());
52    let pb = data_progress(0);
53    let input = LineProcessor::open_gzip(path, pb.clone())?;
54
55    for line in input.records() {
56        nlines += 1;
57        if !line.is_ok() {
58            error!("parse error on line {}", nlines);
59        }
60        let row: Row<R> = line?;
61        proc.write_object(row)?;
62    }
63
64    proc.finish()?;
65
66    Ok(())
67}
68
69impl Command for OpenLib {
70    fn exec(&self) -> Result<()> {
71        match &self.mode {
72            DataType::ScanAuthors(opts) => {
73                scan_openlib(&opts.infile, AuthorProcessor::new()?)?;
74            }
75            DataType::ScanWorks(opts) => {
76                scan_openlib(&opts.infile, WorkProcessor::new()?)?;
77            }
78            DataType::ScanEditions(opts) => {
79                scan_openlib(&opts.infile, EditionProcessor::new()?)?;
80            }
81        };
82
83        Ok(())
84    }
85}