use std::{ collections::{BTreeMap, BTreeSet}, fs::File, io::{self, Seek}, iter::IntoIterator, path::{Path, PathBuf}, }; use miette::Diagnostic; use serde::{Deserialize, Serialize}; use thiserror::Error; use super::CrateVersionSource; use crate::{cargo_home, create_if_not_exist, FileLock}; #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct CratesToml { v1: BTreeMap>, } impl CratesToml { pub fn default_path() -> Result { Ok(cargo_home()?.join(".crates.toml")) } pub fn load() -> Result { Self::load_from_path(Self::default_path()?) } pub fn load_from_reader(mut reader: R) -> Result { let mut vec = Vec::new(); reader.read_to_end(&mut vec)?; Ok(toml_edit::easy::from_slice(&vec)?) } pub fn load_from_path(path: impl AsRef) -> Result { let file = File::open(path)?; Self::load_from_reader(file) } pub fn insert(&mut self, cvs: &CrateVersionSource, bins: BTreeSet) { self.v1.insert(cvs.to_string(), bins); } pub fn write(&self) -> Result<(), CratesTomlParseError> { self.write_to_path(Self::default_path()?) } pub fn write_to_writer(&self, mut writer: W) -> Result<(), CratesTomlParseError> { let data = toml_edit::easy::to_vec(&self)?; writer.write_all(&data)?; Ok(()) } pub fn write_to_file(&self, file: &mut File) -> Result<(), CratesTomlParseError> { self.write_to_writer(&mut *file)?; let pos = file.stream_position()?; file.set_len(pos)?; Ok(()) } pub fn write_to_path(&self, path: impl AsRef) -> Result<(), CratesTomlParseError> { let mut file = File::create(path)?; self.write_to_file(&mut file) } pub fn append_to_path<'a, Iter>( path: impl AsRef, iter: Iter, ) -> Result<(), CratesTomlParseError> where Iter: IntoIterator)>, { let mut file = FileLock::new_exclusive(create_if_not_exist(path.as_ref())?)?; let mut c1 = Self::load_from_reader(&mut *file)?; for (cvs, bins) in iter { c1.insert(cvs, bins); } file.rewind()?; c1.write_to_file(&mut *file)?; Ok(()) } pub fn append<'a, Iter>(iter: Iter) -> Result<(), CratesTomlParseError> where Iter: IntoIterator)>, { Self::append_to_path(Self::default_path()?, iter) } } #[derive(Debug, Diagnostic, Error)] pub enum CratesTomlParseError { #[error(transparent)] Io(#[from] io::Error), #[error(transparent)] TomlParse(#[from] toml_edit::easy::de::Error), #[error(transparent)] TomlWrite(#[from] toml_edit::easy::ser::Error), #[error(transparent)] CvsParse(#[from] super::CvsParseError), }