From 2c1163fc3b7bedcfb1c9d30efce6bbc49aa2d6a7 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Sat, 29 Aug 2026 22:41:11 +0300 Subject: [PATCH] Compress EntityHandle --- src/data/entities.rs | 34 +++++++++-- src/data/repositories.rs | 118 ++++++++++++--------------------------- src/tests.rs | 79 ++++++++++++++++++-------- 3 files changed, 120 insertions(+), 111 deletions(-) diff --git a/src/data/entities.rs b/src/data/entities.rs index e3ff883..7251123 100644 --- a/src/data/entities.rs +++ b/src/data/entities.rs @@ -182,8 +182,7 @@ impl CardStatistics { #[derive(Copy)] pub struct EntityHandle { pub(crate) id: Id, - pub(crate) real: bool, - pub(crate) index: u32, + index: i32, pub(crate) _phantom: PhantomData, } @@ -192,17 +191,40 @@ impl Clone for EntityHandle { fn clone(&self) -> Self { EntityHandle{ id: self.id, - real: self.real, index: self.index, _phantom: Default::default(), } } } +impl EntityHandle { + pub fn new(id: Id, index: usize, real: bool) -> Self { + Self { + id, + index : index as i32 | (!real as i32) << 31, + _phantom: Default::default() + } + } + pub fn index(&self) -> usize { + (self.index << 1 >> 1) as usize + } + + pub fn set_index(&mut self, index: usize) { + self.index = self.index >> 31 << 31 | index as i32; + } + + pub fn real(&self) -> bool { + (self.index >> 31) == 0 + } + + pub fn set_real(&mut self, value: bool) { + self.index = self.index << 1 >> 1 | (!value as i32) << 31; + } +} impl Eq for EntityHandle {} impl PartialEq for EntityHandle { fn eq(&self, other: &Self) -> bool { - self.real == other.real && self.id == other.id + self.real() == other.real() && self.id == other.id } } impl PartialOrd for EntityHandle { @@ -213,11 +235,11 @@ impl PartialOrd for EntityHandle { impl Ord for EntityHandle { fn cmp(&self, other: &Self) -> Ordering { - if self.real && !other.real { + if self.real() && !other.real() { return Ordering::Less } - if !self.real && other.real{ + if !self.real() && other.real(){ return Ordering::Greater } diff --git a/src/data/repositories.rs b/src/data/repositories.rs index 507f3e5..afb9c58 100644 --- a/src/data/repositories.rs +++ b/src/data/repositories.rs @@ -43,7 +43,7 @@ where T: EntityData, { pub(crate) fn handle_save(&self, old: EntityHandle, new: &mut EntityHandle, data: &T) { - if old.real && new.real { + if old.real() && new.real() { return; } @@ -52,7 +52,7 @@ where let mut query = self.queries[q].lock(); let index = query.cache.binary_search(&old).unwrap(); query.cache.remove(index); - let real_end = query.cache.iter().rposition(|r| r.real).unwrap() + 1; + let real_end = query.cache.iter().rposition(|r| r.real()).unwrap() + 1; query.cache.insert(real_end, new.clone()); } } @@ -86,7 +86,6 @@ where for q in &self.queries { let mut query = q.lock(); query.cache.clear(); - } } } @@ -122,7 +121,10 @@ impl, D: DbLayer> Query { } } - pub fn load(&mut self, data_repository: &DataRepositoryInner) where T : Send + Sync { + pub fn load(&mut self, data_repository: &DataRepositoryInner) + where + T: Send + Sync, + { self.cache.clear(); if self.parallel { self.cache = data_repository @@ -130,28 +132,15 @@ impl, D: DbLayer> Query { .par_iter() .enumerate() .filter(|(_, entity)| (self.rule)(entity)) - .map(|(i, entity)| EntityHandle { - id: entity.id(), - real: true, - index: i as u32, - _phantom: PhantomData, - }) + .map(|(i, entity)| EntityHandle::new(entity.id(), i, true)) .collect(); - - - } - else { + } else { self.cache = data_repository .cache .iter() .enumerate() .filter(|(_, entity)| (self.rule)(entity)) - .map(|(i, entity)| EntityHandle { - id: entity.id(), - real: true, - index: i as u32, - _phantom: PhantomData, - }) + .map(|(i, entity)| EntityHandle::new(entity.id(), i, true)) .collect(); } @@ -161,12 +150,7 @@ impl, D: DbLayer> Query { .iter() .enumerate() .filter(|(_, entity)| (self.rule)(entity)) - .map(|(i, entity)| EntityHandle { - id: entity.id(), - real: false, - index: i as u32, - _phantom: PhantomData, - }) + .map(|(i, entity)| EntityHandle::new(entity.id(), i, false)) .collect::>(), ); } @@ -208,6 +192,7 @@ pub struct DataRepositoryInner> connection: Arc>, data_layer: D, query_manger: QueryManger, + version: u16 } impl> Deref for DataRepository { @@ -233,12 +218,7 @@ impl> DataRepository { .par_iter() .enumerate() .filter(|(_, entity)| rule(entity)) - .map(|(i, entity)| EntityHandle { - id: entity.id(), - real: true, - index: i as u32, - _phantom: PhantomData, - }) + .map(|(i, entity)| EntityHandle::new(entity.id(), i, true)) .collect(); cache.extend( @@ -247,12 +227,7 @@ impl> DataRepository { .iter() .enumerate() .filter(|(_, entity)| rule(entity)) - .map(|(i, entity)| EntityHandle { - id: entity.id(), - real: false, - index: i as u32, - _phantom: PhantomData, - }) + .map(|(i, entity)| EntityHandle::new(entity.id(), i, false)) .collect::>(), ); @@ -264,7 +239,10 @@ impl> DataRepository { } } - pub fn query(&self, rule: Box bool + Send + Sync>) -> Query, D> + pub fn query( + &self, + rule: Box bool + Send + Sync>, + ) -> Query, D> where T: Send + Sync, { @@ -275,12 +253,7 @@ impl> DataRepository { .iter() .enumerate() .filter(|(_, entity)| rule(entity)) - .map(|(i, entity)| EntityHandle { - id: entity.id(), - real: true, - index: i as u32, - _phantom: PhantomData, - }) + .map(|(i, entity)| EntityHandle::new(entity.id(), i, true)) .collect(); cache.extend( @@ -289,12 +262,7 @@ impl> DataRepository { .iter() .enumerate() .filter(|(_, entity)| rule(entity)) - .map(|(i, entity)| EntityHandle { - id: entity.id(), - real: false, - index: i as u32, - _phantom: PhantomData, - }) + .map(|(i, entity)| EntityHandle::new(entity.id(), i, false)) .collect::>(), ); @@ -309,7 +277,7 @@ impl> DataRepository { impl> Repository for DataRepositoryInner { fn get(&self, handle: &mut EntityHandle) -> Option { - let slice = if handle.real { + let slice = if handle.real() { self.cache.as_slice() } else { self.temporal.as_slice() @@ -319,7 +287,7 @@ impl> Repository for DataRepositoryIn } fn get_ref(&self, handle: &mut EntityHandle) -> Option<&T> { - let slice = if handle.real { + let slice = if handle.real() { self.cache.as_slice() } else { self.temporal.as_slice() @@ -329,7 +297,7 @@ impl> Repository for DataRepositoryIn } fn get_mut(&mut self, handle: &mut EntityHandle) -> Option<&mut T> { - let slice = if handle.real { + let slice = if handle.real() { self.cache.as_mut_slice() } else { self.temporal.as_mut_slice() @@ -339,23 +307,13 @@ impl> Repository for DataRepositoryIn } fn handle_by_id(&self, id: Id) -> EntityHandle { - EntityHandle { - _phantom: Default::default(), - id, - real: true, - index: id.0, - } + EntityHandle::new(id, id.0 as usize, false) } fn create(&mut self, mut new: T) -> EntityHandle { let next_temporal = self.next_temporal; self.next_temporal += 1; - let entity = EntityHandle { - id: next_temporal.into(), - real: false, - index: self.temporal.len() as u32, - _phantom: PhantomData, - }; + let entity = EntityHandle::new(next_temporal.into(), self.temporal.len(), false); new.set_id(entity.id); self.temporal.push(new); entity @@ -363,7 +321,7 @@ impl> Repository for DataRepositoryIn fn save(&mut self, entity: &mut EntityHandle) -> MaybeError { let original_state = entity.clone(); - if entity.real { + if entity.real() { let data = self.get_ref(entity).unwrap(); self.data_layer .write_entity(data, &self.connection.lock())?; @@ -372,9 +330,9 @@ impl> Repository for DataRepositoryIn let mut data = self.temporal.remove(index); self.data_layer .add_entity(&mut data, &self.connection.lock())?; - entity.real = true; + entity.set_real(true); entity.id = data.id(); - entity.index = self.cache.len() as u32; + entity.set_index(self.cache.len()); self.query_manger.handle_save(original_state, entity, &data); self.cache.push(data); @@ -384,7 +342,7 @@ impl> Repository for DataRepositoryIn } fn delete(&mut self, mut handle: EntityHandle) -> MaybeError { - let vec = if handle.real { + let vec = if handle.real() { self.data_layer .delete_entity(handle.id, &self.connection.lock())?; &mut self.cache @@ -404,6 +362,7 @@ impl> Repository for DataRepositoryIn fn init(&mut self) -> MaybeError { self.data_layer .load_all(&mut self.cache, &self.connection.lock())?; + self.version += 1; Ok(()) } @@ -411,7 +370,6 @@ impl> Repository for DataRepositoryIn self.cache.clear(); self.temporal.clear(); self.init()?; - Ok(()) } } @@ -423,7 +381,7 @@ impl + DbLayer> BatchedRepository 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 { + if handle.real() { cached.push(handle) } else { temp.push(handle) @@ -455,15 +413,13 @@ impl + DbLayer> BatchedRepository let old = handle.clone(); let h = handle; h.id = self.cache[start + i].id(); - h.index = (start + i) as u32; - h.real = true; + h.set_index(start + i); + h.set_real(true); self.query_manger.handle_save(old, h, data); } self.cache.extend(values); - - for handle in cached.into_iter() { let h = handle; let idx = fast_position_of(self.cache.as_slice(), h).unwrap(); @@ -519,7 +475,7 @@ where 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 { + if handle.real() { cached.push(getter(handle)) } else { temp.push(getter(handle)) @@ -537,11 +493,11 @@ pub fn fast_position_of( } let max_idx = storage.len() - 1; - let upper = (handle.index as usize).min(max_idx); + let upper = (handle.index()).min(max_idx); let peek = storage[upper].id(); if peek == handle.id { - handle.index = upper as u32; + handle.set_index(upper); return Some(upper); } @@ -556,7 +512,7 @@ pub fn fast_position_of( let new_index = (upper as i64 - delta).max(0) as usize; if storage[new_index].id() == handle.id { - handle.index = new_index as u32; + handle.set_index(new_index); return Some(new_index); } @@ -569,6 +525,6 @@ pub fn fast_position_of( .ok()? + new_index; - handle.index = index as u32; + handle.set_index(index); Some(index) } diff --git a/src/tests.rs b/src/tests.rs index a49b7f9..c2e777a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -29,12 +29,7 @@ mod mod_tests { #[test] fn search_direct() { - let mut entity = EntityHandle { - _phantom: Default::default(), - id: 8.into(), - real: true, - index: 3, - }; + let mut entity = EntityHandle::new(8.into(), 3, true); assert_eq!( fast_position_of(&[1, 2, 3, 8, 9, 12].map(ProtoEntity::new), &mut entity), Some(3) @@ -43,12 +38,7 @@ mod mod_tests { #[test] fn search_0() { - let mut entity = EntityHandle { - _phantom: Default::default(), - id: 8.into(), - real: true, - index: 4, - }; + let mut entity = EntityHandle::new(8.into(), 4, true); assert_eq!( fast_position_of(&[1, 2, 3, 8, 9, 12].map(ProtoEntity::new), &mut entity), Some(3) @@ -57,12 +47,7 @@ mod mod_tests { #[test] fn search_1() { - let mut entity = EntityHandle { - _phantom: Default::default(), - id: 9.into(), - real: true, - index: 5, - }; + let mut entity = EntityHandle::new(9.into(), 5, true); assert_eq!( fast_position_of(&[1, 2, 3, 8, 9, 12].map(ProtoEntity::new), &mut entity), Some(4) @@ -71,12 +56,7 @@ mod mod_tests { #[test] fn search_2() { - let mut entity = EntityHandle { - _phantom: Default::default(), - id: 106.into(), - real: true, - index: 25, - }; + let mut entity = EntityHandle::new(106.into(), 25, true); assert_eq!( fast_position_of( &[ @@ -89,4 +69,55 @@ mod mod_tests { Some(18) ); } + + #[test] + fn id_0() { + let entity: EntityHandle = EntityHandle::new(8.into(), 25, true); + assert_eq!(entity.real(), true) + } + + #[test] + fn id_1() { + let entity: EntityHandle = EntityHandle::new(8.into(), 25, false); + assert_eq!(entity.real(), false) + } + + #[test] + fn id_3() { + let entity: EntityHandle = EntityHandle::new(8.into(), 25, true); + assert_eq!(entity.index(), 25) + } + + #[test] + fn id_4() { + let entity: EntityHandle = EntityHandle::new(8.into(), 25, false); + assert_eq!(entity.index(), 25) + } + #[test] + fn id_5() { + let mut entity: EntityHandle = EntityHandle::new(8.into(), 25, true); + entity.set_real(true); + assert_eq!(entity.real(), true) + } + + #[test] + fn id_6() { + let mut entity: EntityHandle = EntityHandle::new(8.into(), 25, false); + entity.set_real(true); + assert_eq!(entity.real(), true) + } + + #[test] + fn id_7() { + let mut entity: EntityHandle = EntityHandle::new(8.into(), 25, true); + entity.set_index(0); + assert_eq!(entity.index(), 0) + } + + #[test] + fn id_8() { + let mut entity: EntityHandle = EntityHandle::new(8.into(), 25, false); + entity.set_index(0); + assert_eq!(entity.index(), 0) + } }