caesura 0.11.2

An all-in-one command line tool to **transcode FLAC** audio files and **upload to gazelle** based indexers/trackers.
Documentation
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf};

use colored::Colorize;
use log::trace;

use crate::batch::BatchItem;
use crate::errors::AppError;

pub struct BatchCache {
    pub path: Option<PathBuf>,
    pub items: HashMap<PathBuf, BatchItem>,
}

impl BatchCache {
    pub fn get_queue(&mut self, skip_upload: bool) -> Vec<BatchItem> {
        let mut queue: Vec<BatchItem> = self
            .items
            .values()
            .filter(|x| x.skipped.is_none() && !x.uploaded && (!skip_upload || !x.transcoded))
            .map(Clone::clone)
            .collect();
        queue.sort_by_key(|x| x.path.to_string_lossy().to_string());
        queue
    }

    pub fn update<F>(&mut self, path: &Path, function: F)
    where
        F: FnOnce(&mut BatchItem),
    {
        let key = PathBuf::from(path);
        self.items.entry(key).and_modify(function);
    }

    pub fn save(&self, sort: bool) -> Result<(), AppError> {
        if let Some(path) = &self.path {
            trace!("{} cache file: {path:?}", "Writing".bold());
            let file = File::create(path).or_else(|e| AppError::io(e, "open batch cache"))?;
            let mut writer = BufWriter::new(file);
            let mut items: Vec<&BatchItem> = self.items.values().collect();
            if sort {
                items.sort_by_key(|x| x.path.to_string_lossy().to_string());
            }
            serde_json::to_writer_pretty(&mut writer, &items)
                .or_else(|e| AppError::deserialization(e, "serialize batch cache"))?;
            writer
                .flush()
                .or_else(|e| AppError::external("flush batch cache", "BufWriter", Box::new(e)))?;
        }
        Ok(())
    }
}