diff --git a/src/data/repositories.rs b/src/data/repositories.rs index ee3fa58..1a6967a 100644 --- a/src/data/repositories.rs +++ b/src/data/repositories.rs @@ -1,15 +1,16 @@ use crate::data::Id; -use crate::data::entities::{EntityData, EntityHandle, WordData}; +use crate::data::entities::{EntityData, EntityHandle}; use crate::notification::MaybeError; use parking_lot::{Mutex, RwLock}; use rusqlite::Connection; use std::marker::PhantomData; -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; use std::sync::Arc; -use iced::application::IntoBoot; -use rusqlite::fallible_iterator::Iterator; -pub trait Repository where D : DbLayer { +pub trait Repository +where + D: DbLayer, +{ fn get(&self, handle: &mut EntityHandle) -> Option; fn get_ref(&self, handle: &mut EntityHandle) -> Option<&T>; fn get_mut(&mut self, handle: &mut EntityHandle) -> Option<&mut T>; @@ -21,26 +22,30 @@ pub trait Repository where D : DbLayer { fn reload(&mut self) -> MaybeError; } -pub trait BatchedRepository where D : BatchedDbLayer, T: EntityData +pub trait BatchedRepository +where + D: BatchedDbLayer, + T: EntityData, { fn save_many(&mut self, handles: &mut [EntityHandle]) -> MaybeError; fn delete_many(&mut self, handles: &mut [EntityHandle]) -> MaybeError; - } pub trait DbLayer { fn write_entity(&self, entity: &T, connection: &Connection) -> MaybeError; fn add_entity(&mut self, entity: &mut T, connection: &Connection) -> MaybeError; fn delete_entity(&mut self, id: Id, connection: &Connection) -> MaybeError; - fn load_all(&self, storage: &mut Vec, connection: &Connection) -> MaybeError; + fn load_all(&self, storage: &mut Vec, connection: &Connection) -> MaybeError; } -pub trait BatchedDbLayer where T : EntityData{ +pub trait BatchedDbLayer +where + T: EntityData, +{ fn delete_many(&mut self, ids: &[Id], connection: &Connection) -> MaybeError; fn add_many_entity(&mut self, entity: &mut [T], connection: &Connection) -> MaybeError; } - #[derive(Clone)] pub struct DataRepository { inner: Arc>>, @@ -94,7 +99,7 @@ impl> Repository for DataRepositoryIn } fn handle_by_id(&self, id: Id) -> EntityHandle { - EntityHandle{ + EntityHandle { _phantom: Default::default(), id, real: true, @@ -149,11 +154,13 @@ impl> Repository for DataRepositoryIn fn save(&mut self, entity: &mut EntityHandle) -> MaybeError { if entity.real { let data = self.get_ref(entity).unwrap(); - self.data_layer.write_entity(data, &self.connection.lock())?; + self.data_layer + .write_entity(data, &self.connection.lock())?; } else { let index = fast_position_of(self.temporal.as_slice(), entity).unwrap(); let mut value = self.temporal.remove(index); - self.data_layer.add_entity(&mut value, &self.connection.lock())?; + self.data_layer + .add_entity(&mut value, &self.connection.lock())?; entity.real = true; entity.id = value.id(); entity.index = self.cache.len() as u32; @@ -164,9 +171,9 @@ impl> Repository for DataRepositoryIn } fn delete(&mut self, mut handle: EntityHandle) -> MaybeError { - let vec = if handle.real { - self.data_layer.delete_entity(handle.id, &self.connection.lock())?; + self.data_layer + .delete_entity(handle.id, &self.connection.lock())?; &mut self.cache } else { &mut self.temporal @@ -178,7 +185,8 @@ impl> Repository for DataRepositoryIn } fn init(&mut self) -> MaybeError { - self.data_layer.load_all(&mut self.cache, &self.connection.lock())?; + self.data_layer + .load_all(&mut self.cache, &self.connection.lock())?; Ok(()) } @@ -189,43 +197,109 @@ impl> Repository for DataRepositoryIn Ok(()) } } -impl> BatchedRepository for DataRepositoryInner { +impl + DbLayer> BatchedRepository +for DataRepositoryInner +{ fn save_many(&mut self, handles: &mut [EntityHandle]) -> MaybeError { + let mut temp = Vec::with_capacity(handles.len() / 2); + let mut cached = Vec::with_capacity(handles.len() / 2); + handles.sort_by_key(|a| a.id); + handles.iter_mut().for_each(|handle| { + if handle.real { + cached.push(handle) + } else { + temp.push(handle) + } + }); + + let mut values = Vec::with_capacity(temp.len()); + let mut cell = 0; + let len = temp.len(); + self.temporal.retain(|x| { + if cell == len { + return true; + } + let find = temp[cell].id; + let remove = x.id() == find; + if remove || find > x.id() { + cell += 1; + values.push(x.clone()); + } + !remove + }); + + self.data_layer + .add_many_entity(&mut values, &self.connection.lock())?; + let mut index = self.cache.len(); + values + .iter() + .zip(temp) + .for_each(|(x, y)| { + y.id = x.id(); + y.index = index as u32; + index += 1; + }); + + for in_cache in cached { + let value = self.get_ref(in_cache).unwrap(); + self.data_layer.write_entity(value, &self.connection.lock())?; + } todo!() } fn delete_many(&mut self, handles: &mut [EntityHandle]) -> MaybeError { - let mut temp = Vec::with_capacity(handles.len() / 2); - let mut cached = Vec::with_capacity(handles.len() / 2); - let mut cell = 0; - handles.sort_by(|a, b| {a.id.cmp(&b.id)}); - handles.iter().for_each(|handle| if handle.real { cached.push(handle.id)} else { - temp.push(handle.id) - }); + let (cached, temp) = split_temp_real(handles, |e| e.id); + let mut cell = 0; let len = temp.len(); self.temporal.retain(|x| { - if cell == len { return true; } + if cell == len { + return true; + } let find = temp[cell]; let remove = x.id() == find; - if remove { cell += 1; } + if remove || find > x.id() { + cell += 1; + } !remove }); - self.data_layer.delete_many(cached.as_slice(), &self.connection.lock())?; + self.data_layer + .delete_many(cached.as_slice(), &self.connection.lock())?; let len = cached.len(); cell = 0; self.cache.retain(|x| { - if cell == len { return true; } + if cell == len { + return true; + } let find = cached[cell]; let remove = x.id() == find; - if remove { cell += 1; } + if remove || find > x.id() { + cell += 1; + } !remove }); - Ok(()) + Ok(()) } } +fn split_temp_real(handles: &mut [EntityHandle], getter: F) -> (Vec, Vec) +where + F: Fn(&EntityHandle) -> V, +{ + let mut temp = Vec::with_capacity(handles.len() / 2); + let mut cached = Vec::with_capacity(handles.len() / 2); + handles.sort_by(|a, b| a.id.cmp(&b.id)); + handles.iter().for_each(|handle| { + if handle.real { + cached.push(getter(handle)) + } else { + temp.push(getter(handle)) + } + }); + (cached, temp) +} + pub fn fast_position_of( storage: &[E], handle: &mut EntityHandle,