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 #[arg(name = "INPUT")]
16 infile: PathBuf,
17}
18
19#[derive(clap::Subcommand, Debug)]
20enum DataType {
21 ScanWorks(Input),
25
26 ScanEditions(Input),
30
31 ScanAuthors(Input),
33}
34
35#[derive(Args, Debug)]
37#[command(name = "openlib")]
38pub struct OpenLib {
39 #[command(subcommand)]
40 mode: DataType,
41}
42
43fn 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}