Skip to content

Commit c49ee4f

Browse files
committed
clean up logic for keeping referenced elements, add tests
1 parent 38ea41b commit c49ee4f

8 files changed

Lines changed: 44 additions & 44 deletions

File tree

src/filter/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ fn get_referenced_ids(
101101
pub fn build_keep_list(
102102
filters: &Vec<Box<dyn ElementFilter>>,
103103
chunk_receiver: Receiver<Chunk<Box<[Element]>>>,
104-
) -> HashSet<i64> {
104+
) -> Vec<i64> {
105105
let mut keep_ids = HashSet::new();
106106

107107
// HashMap that stores every relation ID, along with
@@ -154,14 +154,14 @@ pub fn build_keep_list(
154154
}
155155

156156
// Return all IDs of kept elements + their references.
157-
keep_ids_with_references
157+
keep_ids_with_references.into_iter().collect()
158158
}
159159

160160
/// Transform a Vec of boxed ElementFilters into a single function that filters an ElementChunk
161161
pub fn build_filter(
162162
filters: Vec<Box<dyn ElementFilter>>,
163-
) -> Box<dyn Fn(ElementChunk) -> ElementChunk + Sync> {
164-
Box::new(move |chunk: ElementChunk| {
163+
) -> Box<dyn Fn(ElementChunk, Vec<i64>) -> ElementChunk + Sync> {
164+
Box::new(move |chunk: ElementChunk, keep_ids: Vec<i64>| {
165165
let mut out_elements = Vec::new();
166166
for mut element in chunk.content.into_iter() {
167167
let mut keep_element = true;
@@ -173,6 +173,8 @@ pub fn build_filter(
173173
}
174174
if keep_element {
175175
out_elements.push(element);
176+
} else if keep_ids.contains(&element.id) {
177+
out_elements.push(element);
176178
}
177179
}
178180
Chunk {

src/readers/mod.rs

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@ use std::{
66
fs,
77
io::{BufRead, BufReader, Read, stdin},
88
path::PathBuf,
9-
sync::{
10-
Arc, Mutex,
11-
mpsc::{Receiver, Sender, channel},
12-
},
9+
sync::mpsc::{Receiver, Sender, channel},
1310
thread,
1411
};
1512

1613
use crate::{
1714
SkywayError,
18-
chunks::{Chunk, ChunkBuilder, ElementChunk},
15+
chunks::{ChunkBuilder, ElementChunk},
1916
elements::Metadata,
2017
sort::{ElementSorter, SortStrategy},
2118
};
@@ -172,7 +169,7 @@ pub trait Reader: Sized + Clone + Send + 'static {
172169
// and run those resulting ElementChunks through the combined_filter.
173170
let chunk_iterator = self
174171
.read_file(source, metadata_sender, chunk_builder)
175-
.map(|chunk| combined_filter(chunk));
172+
.map(|chunk| combined_filter(chunk, Vec::new()));
176173

177174
// Send out each of those filtered ElementChunks through the correct channel.
178175
chunk_iterator.for_each(|chunk| {
@@ -225,10 +222,6 @@ pub trait Reader: Sized + Clone + Send + 'static {
225222
// Please note that this is where all filtering happens!
226223
let keep_ids = build_keep_list(&filters, first_filter_chunk_receiver);
227224

228-
// Make keep_ids thread-safe
229-
// TODO: Consider performance implications of this.
230-
let keep_ids = Arc::new(Mutex::new(keep_ids));
231-
232225
// "Fake" channel that we won't use, to make the reader thread happy.
233226
// We already read the metadata the first time around.
234227
let (fake_metadata_sender, fake_metadata_receiver) = channel();
@@ -250,37 +243,13 @@ pub trait Reader: Sized + Clone + Send + 'static {
250243
// It is imperative that we re-run the filters, because even though
251244
// we already know which elements we want to keep, we don't know
252245
// what modifications the filters might make to those elements.
253-
.map(|chunk| combined_filter(chunk))
254-
// keep elements depending on if we determined they are necessary above
255-
.for_each(move |chunk| {
256-
// Vec that will hold each element we keep from this ElementChunk.
257-
let mut elements = Vec::new();
258-
259-
// We are iterating through a ParallelIterator, which is why I am
260-
// locking keep_ids here. I reckon there are better ways of
261-
// accomplishing this!
262-
let mut keep_ids_lock = keep_ids.lock().unwrap();
263-
264-
// For each element, push it to the elements Vec (to keep) if it
265-
// existed in the keep_ids Vec. At the same time, remove the ID
266-
// from keep_ids.
267-
//
268-
// TODO: is it really necessary to delete it? Are we really going
269-
// to check if keep_ids is fully exhausted in the end?
270-
for element in chunk.content {
271-
if keep_ids_lock.remove(&element.id) {
272-
elements.push(element);
273-
}
274-
}
275-
// Drop the lock so parallel processes can have their fun with keep_ids
276-
drop(keep_ids_lock);
277-
278-
// Send elements Vec out, neatly packaged as a Chunk
246+
// We pass keep_ids to combined_filter so that it keeps referenced
247+
// elements.
248+
.map(|chunk| combined_filter(chunk, keep_ids.clone()))
249+
// Send chunk out for sorting
250+
.for_each(|chunk| {
279251
filter_chunk_sender
280-
.send(Chunk {
281-
content: elements.into_boxed_slice(),
282-
index: chunk.index,
283-
})
252+
.send(chunk)
284253
.expect("Unable to send chunk.")
285254
});
286255

tests/filter/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
mod references;
2+
13
//mod cel;
24
mod skyfilter;

tests/filter/references/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use crate::define_test;
2+
3+
const CURRENT_DIR: &[&str] = &["filter", "references"];
4+
5+
define_test!(way_references);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name = "Keep Way References"
2+
description = "Ensure that nodes are kept if ways that reference them are kept."
3+
input = "input.opl"
4+
filters = ["keep_one_way.skyfilter"]
5+
expected_output = "expected.opl"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
n3097457072 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.4512421 y37.529974200000005
2+
n3097457044 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.4513172 y37.529842300000006
3+
n3097457089 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.45114550000001 y37.529782700000005
4+
w305163745 v3 dV c26354328 t2014-10-27T01:57:32Z i1408522 uOmnific Tbuilding=yes,name=Abandoned%20%Environmental%20%Center Nn3097457072,n3097457089,n3097457044,n3097457072
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
n3097457039 v2 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.45103040000001 y37.5297835
2+
n3097457072 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.4512421 y37.529974200000005
3+
n3097457124 v3 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.47178100000001 y37.5249898
4+
n3097457044 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.4513172 y37.529842300000006
5+
n3104201899 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.4553514 y37.5294892
6+
n3097457089 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.45114550000001 y37.529782700000005
7+
n3104204256 v1 dV c0 t1970-01-01T00:00:00Z i0 u T x-77.45474250000001 y37.5300188
8+
w305163745 v3 dV c26354328 t2014-10-27T01:57:32Z i1408522 uOmnific Tbuilding=yes,name=Abandoned%20%Environmental%20%Center Nn3097457072,n3097457089,n3097457044,n3097457072
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
SkyFilter v0.6.0
2+
3+
HAS "building"
4+
COMMIT
5+
DROP

0 commit comments

Comments
 (0)