From b112fcfab6cf13c0433c06fe411cbd8d9444d14b Mon Sep 17 00:00:00 2001 From: Lionel Sambuc Date: Tue, 29 Oct 2019 10:46:11 +0100 Subject: [PATCH] Adapting to new Index return type --- src/database/db_core.rs | 79 +++++++++++++++++++------------- src/database/mod.rs | 4 +- src/database/space/coordinate.rs | 4 ++ src/database/space_db.rs | 52 +++++++++++---------- src/database/space_index.rs | 47 +++++++++++++------ src/main.rs | 45 ++++++++++++++---- 6 files changed, 151 insertions(+), 80 deletions(-) diff --git a/src/database/db_core.rs b/src/database/db_core.rs index deb9146..c53c81f 100644 --- a/src/database/db_core.rs +++ b/src/database/db_core.rs @@ -2,6 +2,7 @@ use super::space::Position; use super::space::Shape; use super::space::Space; use super::space_db::SpaceDB; +use super::space_index::SpaceFields; use super::space_index::SpaceSetObject; use super::DataBase; use super::ResultSet; @@ -157,14 +158,18 @@ impl Core { &self.properties } - fn to_space_object(&self, space_id: &str, list: Vec) -> Vec { + fn to_space_object( + &self, + space_id: &str, + list: Vec<(Position, SpaceFields)>, + ) -> Vec { list.into_iter() - .map(|o| { - let offset: usize = o.value().into(); + .map(|(position, fields)| { + let offset: usize = fields.value().into(); let value = self.properties[offset].clone(); SpaceObject { space_id: space_id.to_string(), - position: o.position().clone(), + position: position.clone(), value, } }) @@ -172,7 +177,7 @@ impl Core { } fn decode_positions( - list: &mut [SpaceObject], + list: &mut [(Position, &Properties)], space: &Space, db: &DataBase, output_space: &Option<&str>, @@ -181,18 +186,17 @@ impl Core { let unified = db.space(unified_id)?; // Rebase the point to the requested output space before decoding. - for o in list { - o.position = unified - .decode(&Space::change_base(&o.position, space, unified)?)? + for (position, _) in list { + *position = unified + .decode(&Space::change_base(&position, space, unified)?)? .into(); - o.space_id = unified_id.to_string(); } } else { // Decode the positions into f64 values, which are defined in their // respective reference space. - for o in list { + for (position, _) in list { // Simply decode - o.position = space.decode(&o.position)?.into(); + *position = space.decode(&position)?.into(); } } @@ -233,12 +237,14 @@ impl Core { p.push(to.encode(&position)?); } - let r = s.get_by_positions(&p, parameters)?; - let mut r = self.to_space_object(s.name(), r); + let mut r = s + .get_by_positions(&p, parameters)? + .into_iter() + .map(|(position, fields)| (position, &self.properties[fields.value().as_usize()])) + .collect::>(); + Self::decode_positions(r.as_mut_slice(), to, db, output_space)?; - Self::decode_positions(&mut r, to, db, output_space)?; - - results.append(&mut r); + results.push((s.name(), r)); } Ok(results) @@ -271,12 +277,14 @@ impl Core { // let current_shape = shape.encode(current_space)?; // println!("current shape Encoded: {:?}", current_shape); - let r = s.get_by_shape(¤t_shape, parameters)?; - let mut r = self.to_space_object(s.name(), r); + let mut r = s + .get_by_shape(¤t_shape, parameters)? + .into_iter() + .map(|(position, fields)| (position, &self.properties[fields.value().as_usize()])) + .collect::>(); + Self::decode_positions(r.as_mut_slice(), current_space, db, output_space)?; - Self::decode_positions(&mut r, current_space, db, output_space)?; - - results.append(&mut r); + results.push((s.name(), r)); } Ok(results) @@ -303,13 +311,17 @@ impl Core { // reference space for s in &self.space_db { let current_space = db.space(s.name())?; + let fields = SpaceFields::new(s.name().into(), offset.into()); - let r = s.get_by_id(offset, parameters)?; - let mut r = self.to_space_object(s.name(), r); + let mut r = s + .get_by_id(offset, parameters)? + .into_iter() + .map(|position| (position, &self.properties[fields.value().as_usize()])) + .collect::>(); - Self::decode_positions(&mut r, current_space, db, output_space)?; + Self::decode_positions(r.as_mut_slice(), current_space, db, output_space)?; - results.append(&mut r); + results.push((s.name(), r)); } } @@ -350,9 +362,9 @@ impl Core { Ok(v) => { // Convert the search Volume into Universe. let mut p = vec![]; - for o in v { + for position in v { if let Ok(position) = - Space::change_base(o.position(), from, Space::universe()) + Space::change_base(&position, from, Space::universe()) { p.push(position) } @@ -384,12 +396,17 @@ impl Core { p.push(position); } - let r = s.get_by_positions(&p, parameters)?; - let mut r = self.to_space_object(s.name(), r); + let mut r = s + .get_by_positions(&p, parameters)? + .into_iter() + .map(|(position, fields)| { + (position, &self.properties[fields.value().as_usize()]) + }) + .collect::>(); - Self::decode_positions(&mut r, to, db, output_space)?; + Self::decode_positions(r.as_mut_slice(), to, db, output_space)?; - results.append(&mut r); + results.push((s.name(), r)); } } diff --git a/src/database/mod.rs b/src/database/mod.rs index 03fcc67..26125cc 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -14,9 +14,11 @@ pub use db_core::CoreQueryParameters; pub use db_core::Properties; use space::Position; use space::Space; +pub use space_index::SpaceFields; pub use space_index::SpaceSetObject; -pub type ResultSet = Result, String>; +// (Space Name, Position, Fields) +pub type ResultSet<'r> = Result)>, String>; pub type ReferenceSpaceIndex = ironsea_index_hashmap::Index; type CoreIndex = ironsea_index_hashmap::Index; diff --git a/src/database/space/coordinate.rs b/src/database/space/coordinate.rs index e9c53de..d868ad7 100644 --- a/src/database/space/coordinate.rs +++ b/src/database/space/coordinate.rs @@ -39,6 +39,10 @@ impl Coordinate { Coordinate::CoordinateF64(_v) => unreachable!(), } } + + pub fn as_usize(&self) -> usize { + self.u64() as usize + } } /* diff --git a/src/database/space_db.rs b/src/database/space_db.rs index c482f26..4f00020 100644 --- a/src/database/space_db.rs +++ b/src/database/space_db.rs @@ -99,7 +99,7 @@ impl SpaceDB { let shift = if count >= 31 { 31 } else { count }; count += 1; indices.push(( - SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS), + SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS), vec![power.0, power.0, power.0], shift, )); @@ -118,7 +118,7 @@ impl SpaceDB { // Insert Full resolution index. indices.push(( - SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS), + SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS), vec![count, count, count], 0, // Smallest value => highest resolution )); @@ -157,7 +157,7 @@ impl SpaceDB { } indices.push(( - SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS), + SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS), vec![count, count, count], shift, )); @@ -172,7 +172,7 @@ impl SpaceDB { } else { // Generate only full-scale. indices.push(( - SpaceSetIndex::new(space_objects.into_iter(), DIMENSIONS, CELL_BITS), + SpaceSetIndex::new(space_objects.iter(), DIMENSIONS, CELL_BITS), vec![0, 0, 0], 0, )); @@ -302,12 +302,10 @@ impl SpaceDB { } // Convert the value back to caller's references - fn decode_value(&self, mut objects: Vec) -> Vec { - for o in &mut objects { - o.set_value(self.values[o.value().u64() as usize]); + fn decode_value(&self, objects: &mut Vec<(Position, SpaceFields)>) { + for (_, fields) in objects.iter_mut() { + fields.set_value(self.values[fields.value().u64() as usize]); } - - objects } // Search by Id, a.k.a values @@ -316,7 +314,7 @@ impl SpaceDB { &self, id: usize, parameters: &CoreQueryParameters, - ) -> Result, String> { + ) -> Result, String> { // Is that ID referenced in the current space? if let Ok(offset) = self.values.binary_search(&id.into()) { let index = self.resolution(parameters); @@ -329,20 +327,17 @@ impl SpaceDB { let objects = self.resolutions[index] .find_by_value(&SpaceFields::new(self.name().into(), offset.into())); - let mut results = if let Some(view_port) = view_port { + let results = if let Some(view_port) = view_port { objects .into_iter() - .filter(|o| view_port.contains(o.position())) - .collect::>() + .filter(|position| view_port.contains(position)) + .collect::>() } else { objects }; // Convert the Value back to caller's references // Here we do not use decode() as we have a single id value to manage. - for o in &mut results { - o.set_value(id.into()); - } Ok(results) } else { @@ -356,7 +351,7 @@ impl SpaceDB { &self, positions: &[Position], parameters: &CoreQueryParameters, - ) -> Result, String> { + ) -> Result, String> { let index = self.resolution(parameters); // FIXME: Should I do it here, or add the assumption this is a clean list? @@ -365,13 +360,18 @@ impl SpaceDB { //let view_port = parameters.view_port(space); // Select the objects - let results = positions + let mut results = positions .iter() - .flat_map(|position| self.resolutions[index].find(position)) - .collect::>(); + .flat_map(|position| { + self.resolutions[index] + .find(position) + .into_iter() + .map(move |fields| (position.clone(), fields.clone())) + }) + .collect(); // Decode the Value reference - let results = self.decode_value(results); + self.decode_value(&mut results); Ok(results) } @@ -386,7 +386,7 @@ impl SpaceDB { &self, shape: &Shape, parameters: &CoreQueryParameters, - ) -> Result, String> { + ) -> Result, String> { let index = self.resolution(parameters); // Convert the view port to the encoded space coordinates @@ -394,10 +394,14 @@ impl SpaceDB { let view_port = parameters.view_port(space); // Select the objects - let results = self.resolutions[index].find_by_shape(&shape, &view_port)?; + let mut results = self.resolutions[index] + .find_by_shape(&shape, &view_port)? + .into_iter() + .map(|(position, fields)| (position, fields.clone())) + .collect(); // Decode the Value reference - let results = self.decode_value(results); + self.decode_value(&mut results); Ok(results) } diff --git a/src/database/space_index.rs b/src/database/space_index.rs index 9a5d550..983ac99 100644 --- a/src/database/space_index.rs +++ b/src/database/space_index.rs @@ -7,7 +7,7 @@ use super::space::Position; use super::space::Shape; use super::SpaceId; -#[derive(Clone, Debug, Deserialize, Hash, Serialize)] +#[derive(Clone, Debug, Hash)] pub struct SpaceSetObject { space_id: SpaceId, position: Position, @@ -58,6 +58,22 @@ impl SpaceFields { pub fn new(space_id: SpaceId, value: Coordinate) -> Self { SpaceFields { space_id, value } } + /* + pub fn id(&self) -> &Coordinate { + &self.value + } + + pub fn space_id(&self) -> &SpaceId { + &self.space_id + } + */ + pub fn value(&self) -> &Coordinate { + &self.value + } + + pub fn set_value(&mut self, value: Coordinate) { + self.value = value; + } } impl PartialEq for SpaceFields { @@ -66,13 +82,13 @@ impl PartialEq for SpaceFields { } } -impl ironsea_index::Record for SpaceSetObject { +impl ironsea_index::Record for &SpaceSetObject { fn key(&self) -> Position { self.position.clone() } } -impl ironsea_index::RecordFields for SpaceSetObject { +impl ironsea_index::RecordFields for &SpaceSetObject { fn fields(&self) -> SpaceFields { SpaceFields { space_id: self.space_id().clone(), @@ -109,17 +125,17 @@ impl SpaceIndex { } // Inputs and Results are expressed in encoded space coordinates. - pub fn find(&self, key: &Position) -> Vec { + pub fn find(&self, key: &Position) -> Vec<&SpaceFields> { self.index.find(key) } // Inputs and Results are expressed in encoded space coordinates. - fn find_range(&self, start: &Position, end: &Position) -> Vec { + fn find_range(&self, start: &Position, end: &Position) -> Vec<(Position, &SpaceFields)> { self.index.find_range(start, end) } // Inputs and Results are expressed in encoded space coordinates. - pub fn find_by_value(&self, id: &SpaceFields) -> Vec { + pub fn find_by_value(&self, id: &SpaceFields) -> Vec { self.index.find_by_value(id) } @@ -128,21 +144,22 @@ impl SpaceIndex { &self, shape: &Shape, view_port: &Option, - ) -> Result, String> { + ) -> Result, String> { match shape { Shape::Point(position) => { if let Some(mbb) = view_port { - if mbb.contains(position) { - Ok(self.find(position)) - } else { - Err(format!( + if !mbb.contains(position) { + return Err(format!( "View port '{:?}' does not contain '{:?}'", mbb, position - )) + )); } - } else { - Ok(self.find(position)) } + Ok(self + .find(position) + .into_iter() + .map(|fields| (position.clone(), fields)) + .collect()) } Shape::BoundingBox(bl, bh) => { if let Some(mbb) = view_port { @@ -198,7 +215,7 @@ impl SpaceIndex { let results = self .find_range(&lower, &higher) .into_iter() - .filter(|p| (p.position() - center).norm() <= radius.f64()) + .filter(|(position, _)| (position - center).norm() <= radius.f64()) .collect(); Ok(results) diff --git a/src/main.rs b/src/main.rs index a9dd88b..ec942af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,7 +45,7 @@ fn main() { }; let r = core.get_by_id(&c, id).unwrap(); println!("get_by_id {}: {}", id, r.len()); - println!("{}: {:?}\n", id, r[0]); + println!("{}: {:?}\n", id, r[0].1[0]); let c = CoreQueryParameters { db: &db, @@ -56,7 +56,7 @@ fn main() { }; let r = core.get_by_id(&c, id).unwrap(); println!("get_by_id {}: {}", id, r.len()); - println!("{}: {:?}\n", id, r[0]); + println!("{}: {:?}\n", id, r[0].1[0]); let c = CoreQueryParameters { db: &db, @@ -68,7 +68,7 @@ fn main() { let r = core.get_by_label(&c, id).unwrap(); println!("get_by_label {}: {}", id, r.len()); if !r.is_empty() { - println!("{}: {:?}\n", id, r[0]); + println!("{}: {:?}\n", id, r[0].1[0]); } let lower = space.encode(&[0.2, 0.2, 0.2]).unwrap(); @@ -85,15 +85,41 @@ fn main() { }; let r = core.get_by_shape(&c, &shape, "std").unwrap(); println!("get_by_shape {:?}: {}", shape, r.len()); - println!("{:?}: {:?}\n", shape, r[0]); + println!("{:?}: {:?}\n", shape, r[0].1[0]); - let a = r.iter().filter(|o| o.value.id() == id).collect::>(); + let a = r + .iter() + .filter_map(|(space, v)| { + let v = v + .iter() + .filter(|(_, properties)| properties.id() == id) + .collect::>(); + if v.is_empty() { + None + } else { + Some((space, v)) + } + }) + .collect::>(); println!("get_by_shape A {:?} filtered on {}: {}", shape, id, a.len()); if !a.is_empty() { - println!("{:?}\n", a[0]); + println!("{:?}\n", a[0].1[0]); } - let a = r.iter().filter(|o| o.value.id() != id).collect::>(); + let a = r + .iter() + .filter_map(|(space, v)| { + let v = v + .iter() + .filter(|(_, properties)| properties.id() != id) + .collect::>(); + if v.is_empty() { + None + } else { + Some((space, v)) + } + }) + .collect::>(); println!( "get_by_shape !A {:?} filtered on {}: {}", shape, @@ -101,16 +127,17 @@ fn main() { a.len() ); if !a.is_empty() { - println!("{:?}\n", a[0]); + println!("{:?}\n", a[0].1[0]); } println!( "\nSPACE OBJECT:\n\n{}", serde_json::to_string_pretty(space).unwrap() ); + //FIXME: Not returning SpatialObjects by default println!( "\nSPATIAL OBJECT:\n\n{}", - serde_json::to_string_pretty(a[0]).unwrap() + serde_json::to_string_pretty(&a[0]).unwrap() ); } }