recfile 0.1.4

A library for sequentially reading and writing serialized structured records.
Documentation
use std::{
    num::NonZero,
    path::{self, PathBuf},
};

use clap::Parser;
use recfile::io::v2;
use gskits::pbar::{DEFAULT_INTERVAL, get_bar_pb, get_spin_pb};
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Cli {
    #[arg(long = "in", help = "input rff file")]
    pub in_path: Option<String>,

    #[arg(long = "out", help = "output rff file")]
    pub out_path: Option<String>,

    #[arg(long = "io-depth", default_value_t = 4)]
    pub io_depth: usize,

    #[arg(long = "chunk-size", help = "write chunk size")]
    pub chunk_size: Option<usize>,

    #[arg(long = "rep-times", help = "write total times")]
    pub rep_times: Option<usize>,
}

impl Cli {
    fn get_out_path(&self) -> PathBuf {
        path::Path::new(self.out_path.as_ref().unwrap()).into()
    }

    fn get_in_path(&self) -> PathBuf {
        path::Path::new(self.in_path.as_ref().unwrap()).into()
    }
}

fn write(cli: &Cli) {
    let mut writer =
        v2::RffWriter::new_writer(cli.get_out_path(), NonZero::new(cli.io_depth).unwrap());
    let data = vec!['A' as u8; cli.chunk_size.unwrap_or(1024 * 1024)];
    let tot_size = data.len() * cli.rep_times.expect("rep times must be set");
    let pb = get_bar_pb(
        "writing".to_string(),
        DEFAULT_INTERVAL,
        cli.rep_times.unwrap() as u64,
    );
    let instant = std::time::Instant::now();
    (0..cli.rep_times.unwrap()).into_iter().for_each(|_| {
        pb.inc(1);
        writer.write_serialized_data(&data).unwrap();
    });
    pb.finish();

    let elapsed = instant.elapsed().as_secs_f64();
    let bytes_per_sec = tot_size as f64 / elapsed;
    let mb_per_sec = bytes_per_sec / (1024.0 * 1024.0);
    println!("MB per second: {:.2}MB/s", mb_per_sec);
}

fn read(cli: &Cli) {
    let mut reader =
        v2::RffReader::new_reader(cli.get_in_path(), NonZero::new(cli.io_depth).unwrap());
    let pb = get_spin_pb("reading".to_string(), DEFAULT_INTERVAL);
    let mut tot_size = 0;
    let instant = std::time::Instant::now();
    while let Some(data) = reader.read_serialized_data() {
        pb.inc(1);
        tot_size += data.len();
    }
    pb.finish();

    let elapsed = instant.elapsed().as_secs_f64();
    let bytes_per_sec = tot_size as f64 / elapsed;
    let mb_per_sec = bytes_per_sec / (1024.0 * 1024.0);
    println!("MB per second: {:.2}MB/s", mb_per_sec);
}


fn main() {
    let cli = Cli::parse();
    if cli.in_path.is_some() {
        write(&cli);
    }
    if cli.out_path.is_some() {
        read(&cli);
    }
}