mirror of
https://github.com/Dangoware/dmp-core.git
synced 2025-04-19 09:52:55 -05:00
Implemented new reading/writing in utils, improved library init function
This commit is contained in:
parent
0f49c50c42
commit
0f5eda5d1d
5 changed files with 108 additions and 78 deletions
14
.gitignore
vendored
14
.gitignore
vendored
|
@ -1,9 +1,15 @@
|
|||
# Rust binary output dir
|
||||
target/
|
||||
|
||||
music_database*
|
||||
*.db3*
|
||||
config.toml
|
||||
# Rust configuration
|
||||
Cargo.lock
|
||||
|
||||
# Database files
|
||||
*.db3*
|
||||
music_database*
|
||||
|
||||
# Storage formats
|
||||
*.kate-swp*
|
||||
*.m3u
|
||||
*.m3u8
|
||||
*.m3u8
|
||||
*.json
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use std::{path::{PathBuf, Path}, marker::PhantomData, fs::{File, OpenOptions, self}, io::{Error, Write, Read}, default};
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
fs::{File, OpenOptions, self},
|
||||
io::{Error, Write, Read},
|
||||
};
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::{to_string, to_string_pretty};
|
||||
use serde_json::to_string_pretty;
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -11,6 +15,7 @@ pub struct ConfigLibrary {
|
|||
pub path: PathBuf,
|
||||
pub uuid: Uuid
|
||||
}
|
||||
|
||||
impl ConfigLibrary {
|
||||
pub fn new() -> Self {
|
||||
ConfigLibrary::default()
|
||||
|
@ -22,6 +27,7 @@ impl ConfigLibrary {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ConfigLibrary {
|
||||
fn default() -> Self {
|
||||
ConfigLibrary {
|
||||
|
@ -31,29 +37,71 @@ impl Default for ConfigLibrary {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct ConfigLibraries {
|
||||
default_library: Uuid,
|
||||
pub library_folder: PathBuf,
|
||||
pub libraries: Vec<ConfigLibrary>,
|
||||
}
|
||||
|
||||
impl ConfigLibraries {
|
||||
//TODO: Add new function for test tube
|
||||
pub fn set_default(mut self, uuid: &Uuid) {
|
||||
self.default_library = *uuid;
|
||||
}
|
||||
|
||||
pub fn get_default(&self) -> Result<&ConfigLibrary, ConfigError> {
|
||||
for library in &self.libraries {
|
||||
if library.uuid == self.default_library {
|
||||
return Ok(library)
|
||||
}
|
||||
}
|
||||
Err(ConfigError::NoDefaultLibrary)
|
||||
}
|
||||
|
||||
pub fn get_library(&self, uuid: &Uuid) -> Result<ConfigLibrary, ConfigError> {
|
||||
for library in &self.libraries {
|
||||
if &library.uuid == uuid {
|
||||
return Ok(library.to_owned())
|
||||
}
|
||||
}
|
||||
Err(ConfigError::NoConfigLibrary(*uuid))
|
||||
}
|
||||
|
||||
pub fn uuid_exists(&self, uuid: &Uuid) -> bool {
|
||||
for library in &self.libraries {
|
||||
if &library.uuid == uuid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub path: PathBuf,
|
||||
pub libraries: ConfigLibraries,
|
||||
volume: f32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn config_test_() {
|
||||
Config {
|
||||
path: PathBuf::from("F:\\temp\\config.json"),
|
||||
fn config_test() {
|
||||
let _ = Config {
|
||||
path: PathBuf::from("config_test.json"),
|
||||
libraries: ConfigLibraries {
|
||||
libraries: vec![ConfigLibrary::default(),ConfigLibrary::default(),ConfigLibrary::default()],
|
||||
libraries: vec![
|
||||
ConfigLibrary::default(),
|
||||
ConfigLibrary::default(),
|
||||
ConfigLibrary::default()
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}.to_file();
|
||||
}.write_file();
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new() -> Self {
|
||||
Config {
|
||||
|
@ -64,38 +112,12 @@ impl Config {
|
|||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_main() -> Self {
|
||||
Config::default()
|
||||
}
|
||||
//TODO: Add new function for test tube
|
||||
pub fn set_default_library(mut self, uuid: &Uuid) {
|
||||
self.libraries.default_library = *uuid;
|
||||
}
|
||||
pub fn get_default_library(&self) -> Result<&ConfigLibrary, ConfigError> {
|
||||
for library in &self.libraries.libraries {
|
||||
if library.uuid == self.libraries.default_library {
|
||||
return Ok(library)
|
||||
}
|
||||
}
|
||||
Err(ConfigError::NoDefaultLibrary)
|
||||
}
|
||||
pub fn get_library(&self, uuid: &Uuid) -> Result<ConfigLibrary, ConfigError> {
|
||||
for library in &self.libraries.libraries {
|
||||
if &library.uuid == uuid {
|
||||
return Ok(library.to_owned())
|
||||
}
|
||||
}
|
||||
Err(ConfigError::NoConfigLibrary(*uuid))
|
||||
}
|
||||
pub fn library_exists(&self, uuid: &Uuid) -> bool {
|
||||
for library in &self.libraries.libraries {
|
||||
if &library.uuid == uuid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
pub fn to_file(&self) -> Result<(), Error> {
|
||||
|
||||
pub fn write_file(&self) -> Result<(), Error> {
|
||||
let mut writer = self.path.clone();
|
||||
writer.set_extension("tmp");
|
||||
let mut file = OpenOptions::new().create(true).truncate(true).read(true).write(true).open(&writer)?;
|
||||
|
@ -106,7 +128,8 @@ impl Config {
|
|||
fs::rename(writer, self.path.as_path())?;
|
||||
Ok(())
|
||||
}
|
||||
pub fn load_file(path: PathBuf) -> Result<Self, Error> {
|
||||
|
||||
pub fn read_file(path: PathBuf) -> Result<Self, Error> {
|
||||
let mut file: File = File::open(path)?;
|
||||
let mut bun: String = String::new();
|
||||
_ = file.read_to_string(&mut bun);
|
||||
|
|
|
@ -3,6 +3,8 @@ pub mod music_storage {
|
|||
pub mod music_collection;
|
||||
pub mod playlist;
|
||||
mod utils;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub mod db_reader;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Crate things
|
||||
use super::utils::{find_images, normalize, read_library, write_library};
|
||||
use super::music_collection::MusicCollection;
|
||||
use super::utils::{find_images, normalize, read_file, write_file};
|
||||
use crate::config::config::Config;
|
||||
use crate::music_storage::library;
|
||||
|
||||
// Various std things
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -316,25 +314,30 @@ impl Album<'_> {
|
|||
|
||||
const BLOCKED_EXTENSIONS: [&str; 4] = ["vob", "log", "txt", "sf2"];
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MusicLibrary {
|
||||
pub name: String,
|
||||
pub uuid: Uuid,
|
||||
pub library: Vec<Song>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_() {
|
||||
let a = MusicLibrary::init(Arc::new(RwLock::from(Config::new())), None).unwrap();
|
||||
dbg!(a);
|
||||
}
|
||||
fn library_init() {
|
||||
let uuidv4 = Uuid::new_v4();
|
||||
let a = MusicLibrary::init(Arc::new(RwLock::from(Config::new())), uuidv4).unwrap();
|
||||
dbg!(a);
|
||||
}
|
||||
|
||||
impl MusicLibrary {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(name: String, uuid: Uuid) -> Self {
|
||||
MusicLibrary {
|
||||
name: String::default(),
|
||||
uuid: Uuid::default(),
|
||||
name,
|
||||
uuid,
|
||||
library: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn with_uuid(uuid: Uuid, path: PathBuf) -> Result<Self, Box<dyn Error>> {
|
||||
MusicLibrary {
|
||||
name: String::new(),
|
||||
|
@ -344,40 +347,35 @@ impl MusicLibrary {
|
|||
|
||||
todo!()
|
||||
}
|
||||
*/
|
||||
|
||||
/// Initialize the database
|
||||
///
|
||||
/// If the database file already exists, return the [MusicLibrary], otherwise create
|
||||
/// the database first. This needs to be run before anything else to retrieve
|
||||
/// the [MusicLibrary] Vec
|
||||
pub fn init(config: Arc<RwLock<Config>>, uuid: Option<Uuid>) -> Result<Self, Box<dyn Error>> {
|
||||
pub fn init(config: Arc<RwLock<Config>>, uuid: Uuid) -> Result<Self, Box<dyn Error>> {
|
||||
let global_config = &*config.read().unwrap();
|
||||
|
||||
let mut library = MusicLibrary::new();
|
||||
let library: MusicLibrary = match global_config.libraries.uuid_exists(&uuid) {
|
||||
true => read_file(global_config.libraries.get_library(&uuid)?.path)?,
|
||||
false => {
|
||||
// If the library does not exist, re-create it
|
||||
let lib = MusicLibrary::new(String::new(), uuid);
|
||||
write_file(&lib, global_config.libraries.get_library(&uuid)?.path)?;
|
||||
lib
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(uuid) = uuid {
|
||||
match global_config.library_exists(&uuid) {
|
||||
true => {
|
||||
library.library = read_library(global_config.get_library(&uuid)?.path)?;
|
||||
},
|
||||
false => {
|
||||
// Create the database if it does not exist
|
||||
write_library(&library.library, global_config.path.clone())?;
|
||||
library = MusicLibrary::with_uuid(uuid, global_config.path.parent().unwrap().to_path_buf())?;
|
||||
}
|
||||
};
|
||||
}else {
|
||||
write_library(&library.library, global_config.path.clone())?;
|
||||
}
|
||||
Ok(library)
|
||||
}
|
||||
|
||||
/// Serializes the database out to the file specified in the config
|
||||
pub fn save(&self, config: &Config) -> Result<(), Box<dyn Error>> {
|
||||
let path = config.get_library(&self.uuid)?.path;
|
||||
let path = config.libraries.get_library(&self.uuid)?.path;
|
||||
match path.try_exists() {
|
||||
Ok(_) => {
|
||||
write_library(&self.library, path)?;
|
||||
write_file(&self.library, path)?;
|
||||
}
|
||||
Err(error) => return Err(error.into()),
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use walkdir::WalkDir;
|
|||
|
||||
use snap;
|
||||
|
||||
use super::library::{AlbumArt, Song, URI};
|
||||
use super::library::{AlbumArt, URI};
|
||||
use unidecode::unidecode;
|
||||
|
||||
pub(super) fn normalize(input_string: &str) -> String {
|
||||
|
@ -19,35 +19,36 @@ pub(super) fn normalize(input_string: &str) -> String {
|
|||
normalized
|
||||
}
|
||||
|
||||
pub(super) fn read_library(path: PathBuf) -> Result<Vec<Song>, Box<dyn Error>> {
|
||||
pub(super) fn read_file<T: for<'de> serde::Deserialize<'de>>(path: PathBuf) -> Result<T, Box<dyn Error>> {
|
||||
// Create a new snap reader over the database file
|
||||
let database = fs::File::open(path)?;
|
||||
let reader = BufReader::new(database);
|
||||
let mut d = snap::read::FrameDecoder::new(reader);
|
||||
|
||||
// Decode the library from the serialized data into the vec
|
||||
let library: Vec<Song> = bincode::serde::decode_from_std_read(
|
||||
let library: T = bincode::serde::decode_from_std_read(
|
||||
&mut d,
|
||||
bincode::config::standard()
|
||||
.with_little_endian()
|
||||
.with_variable_int_encoding(),
|
||||
)?;
|
||||
|
||||
Ok(library)
|
||||
}
|
||||
|
||||
pub(super) fn write_library(
|
||||
library: &Vec<Song>,
|
||||
pub(super) fn write_file<T: serde::Serialize>(
|
||||
library: &T,
|
||||
path: PathBuf,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
// Create 2 new names for the file, a temporary one for writing out, and a backup
|
||||
// Create a temporary name for writing out
|
||||
let mut writer_name = path.clone();
|
||||
writer_name.set_extension("tmp");
|
||||
|
||||
// Create a new BufWriter on the file and make a snap frame encoer for it too
|
||||
// Create a new BufWriter on the file and a snap frame encoder
|
||||
let writer = BufWriter::new(fs::File::create(&writer_name)?);
|
||||
let mut e = snap::write::FrameEncoder::new(writer);
|
||||
|
||||
// Write out the data using bincode
|
||||
// Write out the data
|
||||
bincode::serde::encode_into_std_write(
|
||||
library,
|
||||
&mut e,
|
||||
|
|
Loading…
Reference in a new issue