Avoid cloning strings

This commit is contained in:
Wojciech Kozlowski 2024-02-10 19:06:46 +01:00
parent cc20c9f3dc
commit a211d120d1
4 changed files with 54 additions and 36 deletions

View File

@ -10,7 +10,7 @@ use crate::core::{
database::{IDatabase, LoadError, SaveError}, database::{IDatabase, LoadError, SaveError},
}; };
use super::serde::Database; use super::serde::{deserialize::DeserializeDatabase, serialize::SerializeDatabase};
impl From<serde_json::Error> for LoadError { impl From<serde_json::Error> for LoadError {
fn from(err: serde_json::Error) -> LoadError { fn from(err: serde_json::Error) -> LoadError {
@ -50,12 +50,12 @@ impl<JDB: IJsonDatabaseBackend> JsonDatabase<JDB> {
impl<JDB: IJsonDatabaseBackend> IDatabase for JsonDatabase<JDB> { impl<JDB: IJsonDatabaseBackend> IDatabase for JsonDatabase<JDB> {
fn load(&self) -> Result<Collection, LoadError> { fn load(&self) -> Result<Collection, LoadError> {
let serialized = self.backend.read()?; let serialized = self.backend.read()?;
let database: Database = serde_json::from_str(&serialized)?; let database: DeserializeDatabase = serde_json::from_str(&serialized)?;
database.try_into() database.try_into()
} }
fn save(&mut self, collection: &Collection) -> Result<(), SaveError> { fn save(&mut self, collection: &Collection) -> Result<(), SaveError> {
let database: Database = collection.into(); let database: SerializeDatabase = collection.into();
let serialized = serde_json::to_string(&database)?; let serialized = serde_json::to_string(&database)?;
self.backend.write(&serialized)?; self.backend.write(&serialized)?;
Ok(()) Ok(())
@ -135,7 +135,7 @@ mod tests {
#[test] #[test]
fn load_errors() { fn load_errors() {
let json = String::from(""); let json = String::from("");
let serde_err = serde_json::from_str::<Database>(&json); let serde_err = serde_json::from_str::<DeserializeDatabase>(&json);
assert!(serde_err.is_err()); assert!(serde_err.is_err());
let serde_err: LoadError = serde_err.unwrap_err().into(); let serde_err: LoadError = serde_err.unwrap_err().into();

View File

@ -1,3 +1,7 @@
use std::collections::HashMap;
use serde::Deserialize;
use crate::{ use crate::{
collection::{ collection::{
self, self,
@ -5,17 +9,24 @@ use crate::{
}, },
core::{ core::{
collection::{artist::Artist, Collection}, collection::{artist::Artist, Collection},
database::{ database::{serde::Database, LoadError},
serde::{Database, DbArtist},
LoadError,
},
}, },
}; };
impl TryFrom<Database> for Collection { pub type DeserializeDatabase = Database<DeserializeArtist>;
#[derive(Debug, Deserialize)]
pub struct DeserializeArtist {
name: String,
sort: Option<String>,
musicbrainz: Option<String>,
properties: HashMap<String, Vec<String>>,
}
impl TryFrom<DeserializeDatabase> for Collection {
type Error = LoadError; type Error = LoadError;
fn try_from(database: Database) -> Result<Self, Self::Error> { fn try_from(database: DeserializeDatabase) -> Result<Self, Self::Error> {
match database { match database {
Database::V20240210(collection) => collection Database::V20240210(collection) => collection
.into_iter() .into_iter()
@ -25,15 +36,15 @@ impl TryFrom<Database> for Collection {
} }
} }
impl TryFrom<DbArtist> for Artist { impl TryFrom<DeserializeArtist> for Artist {
type Error = LoadError; type Error = LoadError;
fn try_from(artist: DbArtist) -> Result<Self, Self::Error> { fn try_from(artist: DeserializeArtist) -> Result<Self, Self::Error> {
Ok(Artist { Ok(Artist {
id: ArtistId::new(artist.name), id: ArtistId::new(artist.name),
sort: artist.sort.map(ArtistId::new), sort: artist.sort.map(ArtistId::new),
musicbrainz: artist.musicbrainz.map(MusicBrainz::new).transpose()?, musicbrainz: artist.musicbrainz.map(MusicBrainz::new).transpose()?,
properties: artist.properties.into_iter().collect(), properties: artist.properties,
albums: vec![], albums: vec![],
}) })
} }

View File

@ -3,20 +3,9 @@
pub mod deserialize; pub mod deserialize;
pub mod serialize; pub mod serialize;
use std::collections::BTreeMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum Database { pub enum Database<ARTIST> {
V20240210(Vec<DbArtist>), V20240210(Vec<ARTIST>),
}
// FIXME: try with references to original values.
#[derive(Debug, Serialize, Deserialize)]
pub struct DbArtist {
pub name: String,
pub sort: Option<String>,
pub musicbrainz: Option<String>,
pub properties: BTreeMap<String, Vec<String>>,
} }

View File

@ -1,21 +1,39 @@
use std::collections::BTreeMap;
use serde::Serialize;
use crate::core::{ use crate::core::{
collection::{artist::Artist, Collection}, collection::{artist::Artist, Collection},
database::serde::{Database, DbArtist}, database::serde::Database,
}; };
impl From<&Collection> for Database { pub type SerializeDatabase<'a> = Database<SerializeArtist<'a>>;
fn from(collection: &Collection) -> Self {
#[derive(Debug, Serialize)]
pub struct SerializeArtist<'a> {
name: &'a str,
sort: Option<&'a str>,
musicbrainz: Option<&'a str>,
properties: BTreeMap<&'a str, &'a Vec<String>>,
}
impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
fn from(collection: &'a Collection) -> Self {
Database::V20240210(collection.iter().map(|artist| artist.into()).collect()) Database::V20240210(collection.iter().map(|artist| artist.into()).collect())
} }
} }
impl From<&Artist> for DbArtist { impl<'a> From<&'a Artist> for SerializeArtist<'a> {
fn from(artist: &Artist) -> Self { fn from(artist: &'a Artist) -> Self {
DbArtist { SerializeArtist {
name: artist.id.name.clone(), name: &artist.id.name,
sort: artist.sort.clone().map(|id| id.name), sort: artist.sort.as_ref().map(|id| id.name.as_ref()),
musicbrainz: artist.musicbrainz.clone().map(|mb| mb.as_ref().to_owned()), musicbrainz: artist.musicbrainz.as_ref().map(|mb| mb.as_ref()),
properties: artist.properties.clone().into_iter().collect(), properties: artist
.properties
.iter()
.map(|(k, v)| (k.as_ref(), v))
.collect(),
} }
} }
} }