Switch to iterators
This commit is contained in:
180
src/sfc.rs
180
src/sfc.rs
@@ -28,13 +28,13 @@ type SFCOffset = u32;
|
|||||||
// type-num crate?
|
// type-num crate?
|
||||||
const MAX_K: usize = 3;
|
const MAX_K: usize = 3;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Limit<V> {
|
struct Limit<V> {
|
||||||
idx: usize,
|
idx: usize,
|
||||||
position: Vec<V>,
|
position: Vec<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Limits<'a, V> {
|
struct Limits<'a, V> {
|
||||||
start: Limit<&'a V>,
|
start: Limit<&'a V>,
|
||||||
end: Limit<&'a V>,
|
end: Limit<&'a V>,
|
||||||
@@ -154,19 +154,25 @@ where
|
|||||||
|
|
||||||
/// Returns a vector of keys which have stored values in the index
|
/// Returns a vector of keys which have stored values in the index
|
||||||
/// equal to `value`.
|
/// equal to `value`.
|
||||||
pub fn find_by_value(&self, value: &F) -> Vec<K> {
|
pub fn find_by_value<'s>(&'s self, value: &'s F) -> Box<dyn Iterator<Item = K> + 's> {
|
||||||
let mut results = vec![];
|
Box::new(
|
||||||
for cell in &self.index {
|
self.index
|
||||||
for record in &cell.records {
|
.iter()
|
||||||
if &record.fields == value {
|
.map(|cell| (cell, cell.records.iter()))
|
||||||
if let Ok(key) = self.position(cell.code, &record.offsets) {
|
.flat_map(move |(cell, records)| {
|
||||||
results.push(key);
|
records.filter_map(move |record| {
|
||||||
}
|
if &record.fields == value {
|
||||||
}
|
if let Ok(key) = self.position(cell.code, &record.offsets) {
|
||||||
}
|
Some(key)
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
results
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map the cell_ids of a point to its SFCcode
|
// Map the cell_ids of a point to its SFCcode
|
||||||
@@ -249,95 +255,101 @@ where
|
|||||||
K: Debug + FromIterator<V> + Index<usize, Output = V>,
|
K: Debug + FromIterator<V> + Index<usize, Output = V>,
|
||||||
V: Clone + Debug + From<usize> + Hash + Ord,
|
V: Clone + Debug + From<usize> + Hash + Ord,
|
||||||
{
|
{
|
||||||
fn find(&self, key: &K) -> Vec<&F> {
|
fn find<'i>(&'i self, key: &K) -> Box<dyn Iterator<Item = &F> + 'i> {
|
||||||
let mut values = vec![];
|
|
||||||
|
|
||||||
if let Ok((cell_ids, offsets)) = self.space.key(key) {
|
if let Ok((cell_ids, offsets)) = self.space.key(key) {
|
||||||
match self.encode(&cell_ids) {
|
match self.encode(&cell_ids) {
|
||||||
Err(e) => error!("{}", e),
|
Err(e) => error!("{}", e),
|
||||||
Ok(code) => {
|
Ok(code) => {
|
||||||
if let Ok(cell) = self.index.binary_search_by(|a| a.code.cmp(&code)) {
|
if let Ok(cell) = self.index.binary_search_by(|a| a.code.cmp(&code)) {
|
||||||
for record in &self.index[cell].records {
|
return Box::new(self.index[cell].records.iter().filter_map(
|
||||||
let mut select = true;
|
move |record| {
|
||||||
for (k, o) in offsets.iter().enumerate().take(self.dimensions) {
|
let mut select = true;
|
||||||
select &= record.offsets[k] == (*o as SFCOffset);
|
for (k, o) in offsets.iter().enumerate().take(self.dimensions) {
|
||||||
}
|
select &= record.offsets[k] == (*o as SFCOffset);
|
||||||
|
}
|
||||||
|
|
||||||
if select {
|
if select {
|
||||||
values.push(&record.fields);
|
Some(&record.fields)
|
||||||
}
|
} else {
|
||||||
}
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
values
|
Box::new(Vec::with_capacity(0).into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_range(&self, start: &K, end: &K) -> Vec<(K, &F)> {
|
fn find_range<'i>(&'i self, start: &K, end: &K) -> Box<dyn Iterator<Item = (K, &F)> + 'i> {
|
||||||
let mut values = vec![];
|
|
||||||
|
|
||||||
match self.limits(start, end) {
|
match self.limits(start, end) {
|
||||||
Ok(limits) => {
|
Ok(limits) => {
|
||||||
for idx in limits.start.idx..limits.end.idx {
|
let iter = (limits.start.idx..limits.end.idx)
|
||||||
let code = self.index[idx].code;
|
.filter_map(move |idx| {
|
||||||
|
match self.value(self.index[idx].code, &self.index[idx].records[0].offsets)
|
||||||
let first = match self.value(code, &self.index[idx].records[0].offsets) {
|
{
|
||||||
Err(e) => {
|
Err(_) => None,
|
||||||
error!("Cannot retrieve first value of cell: {}", e);
|
Ok(first) => Some((idx, first)),
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
Ok(r) => r,
|
})
|
||||||
};
|
.filter_map(move |(idx, first)| {
|
||||||
|
let (cell_ids, last_offsets) = self.last();
|
||||||
let (cell_ids, last_offsets) = self.last();
|
match self.space.value(cell_ids, last_offsets) {
|
||||||
let last = match self.space.value(cell_ids, last_offsets) {
|
Err(_) => None,
|
||||||
Err(e) => {
|
Ok(last) => Some((idx, first, last)),
|
||||||
error!("Cannot retrieve last value of cell: {}", e);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
Ok(r) => r,
|
})
|
||||||
};
|
.map(move |(idx, first, last)| {
|
||||||
|
// Check first & last point of the cell, if both are fully
|
||||||
// Check first & last point of the cell, if both are fully
|
// in the bounding box, then all the points of the cell will
|
||||||
// in the bounding box, then all the points of the cell will
|
// be.
|
||||||
// be.
|
let limits = limits.clone();
|
||||||
if limits.start.position <= first
|
let b: Box<dyn Iterator<Item = _>> = if limits.start.position <= first
|
||||||
&& first <= limits.end.position
|
&& first <= limits.end.position
|
||||||
&& limits.start.position <= last
|
&& limits.start.position <= last
|
||||||
&& last <= limits.end.position
|
&& last <= limits.end.position
|
||||||
{
|
{
|
||||||
for record in &self.index[idx].records {
|
Box::new(self.index[idx].records.iter().filter_map(move |record| {
|
||||||
if let Ok(key) = self.position(code, &record.offsets) {
|
let code = self.index[idx].code;
|
||||||
values.push((key, &record.fields));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We have points which are outside of the bounding box,
|
|
||||||
// so check every points one by one.
|
|
||||||
for record in &self.index[idx].records {
|
|
||||||
let pos = match self.value(code, &record.offsets) {
|
|
||||||
Err(e) => {
|
|
||||||
error!("{}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Ok(r) => r,
|
|
||||||
};
|
|
||||||
|
|
||||||
if limits.start.position <= pos && pos <= limits.end.position {
|
|
||||||
if let Ok(key) = self.position(code, &record.offsets) {
|
if let Ok(key) = self.position(code, &record.offsets) {
|
||||||
values.push((key, &record.fields));
|
Some((key, &record.fields))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}))
|
||||||
}
|
} else {
|
||||||
}
|
// We have points which are outside of the bounding box,
|
||||||
}
|
// so check every points one by one.
|
||||||
}
|
Box::new(self.index[idx].records.iter().filter_map(move |record| {
|
||||||
Err(e) => error!("find_range: limits failed: {}", e),
|
let code = self.index[idx].code;
|
||||||
};
|
if let Ok(pos) = self.value(code, &record.offsets) {
|
||||||
|
if limits.start.position <= pos && pos <= limits.end.position {
|
||||||
|
if let Ok(key) = self.position(code, &record.offsets) {
|
||||||
|
Some((key, &record.fields))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
values
|
b
|
||||||
|
})
|
||||||
|
.flatten();
|
||||||
|
Box::new(iter)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("find_range: limits failed: {}", e);
|
||||||
|
Box::new(Vec::with_capacity(0).into_iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user