use crate::blob_meta::ElemKind;
use crate::osc::CompactDiffOverlay;
pub(super) struct DiffRanges {
pub(super) node_ids: Vec<i64>,
pub(super) way_ids: Vec<i64>,
pub(super) rel_ids: Vec<i64>,
node_upserts: Vec<i64>,
way_upserts: Vec<i64>,
rel_upserts: Vec<i64>,
}
impl DiffRanges {
#[cfg_attr(feature = "hotpath", hotpath::measure)]
pub(super) fn from_diff(diff: &CompactDiffOverlay) -> Self {
let mut node_ids: Vec<i64> = diff
.node_ids()
.chain(diff.deleted_nodes.iter())
.copied()
.collect();
node_ids.sort_unstable_by(|a, b| crate::osm_id::osm_id_cmp(*a, *b));
node_ids.dedup();
let mut way_ids: Vec<i64> = diff
.way_ids()
.chain(diff.deleted_ways.iter())
.copied()
.collect();
way_ids.sort_unstable_by(|a, b| crate::osm_id::osm_id_cmp(*a, *b));
way_ids.dedup();
let mut rel_ids: Vec<i64> = diff
.relation_ids()
.chain(diff.deleted_relations.iter())
.copied()
.collect();
rel_ids.sort_unstable_by(|a, b| crate::osm_id::osm_id_cmp(*a, *b));
rel_ids.dedup();
let mut node_upserts: Vec<i64> = diff.node_ids().copied().collect();
node_upserts.sort_unstable_by(|a, b| crate::osm_id::osm_id_cmp(*a, *b));
node_upserts.dedup();
let mut way_upserts: Vec<i64> = diff.way_ids().copied().collect();
way_upserts.sort_unstable_by(|a, b| crate::osm_id::osm_id_cmp(*a, *b));
way_upserts.dedup();
let mut rel_upserts: Vec<i64> = diff.relation_ids().copied().collect();
rel_upserts.sort_unstable_by(|a, b| crate::osm_id::osm_id_cmp(*a, *b));
rel_upserts.dedup();
Self {
node_ids,
way_ids,
rel_ids,
node_upserts,
way_upserts,
rel_upserts,
}
}
pub(super) fn range_overlaps(&self, kind: ElemKind, min_id: i64, max_id: i64) -> bool {
let ids = match kind {
ElemKind::Node => &self.node_ids,
ElemKind::Way => &self.way_ids,
ElemKind::Relation => &self.rel_ids,
};
if ids.is_empty() {
return false;
}
let first = crate::osm_id::blob_osm_first_key(min_id, max_id);
let last = crate::osm_id::blob_osm_last_key(min_id, max_id);
let pos = ids.partition_point(|&id| crate::osm_id::osm_id_key(id) < first);
pos < ids.len() && crate::osm_id::osm_id_key(ids[pos]) <= last
}
pub(super) fn upserts(&self, kind: ElemKind) -> &[i64] {
match kind {
ElemKind::Node => &self.node_upserts,
ElemKind::Way => &self.way_upserts,
ElemKind::Relation => &self.rel_upserts,
}
}
}
pub(super) struct UpsertCursors {
node: usize,
way: usize,
rel: usize,
}
impl UpsertCursors {
pub(super) fn new() -> Self {
Self { node: 0, way: 0, rel: 0 }
}
pub(super) fn get_mut<'a>(&mut self, kind: ElemKind, ranges: &'a DiffRanges) -> (&mut usize, &'a [i64]) {
match kind {
ElemKind::Node => (&mut self.node, ranges.upserts(ElemKind::Node)),
ElemKind::Way => (&mut self.way, ranges.upserts(ElemKind::Way)),
ElemKind::Relation => (&mut self.rel, ranges.upserts(ElemKind::Relation)),
}
}
pub(super) fn get<'a>(&self, kind: ElemKind, ranges: &'a DiffRanges) -> (usize, &'a [i64]) {
match kind {
ElemKind::Node => (self.node, ranges.upserts(ElemKind::Node)),
ElemKind::Way => (self.way, ranges.upserts(ElemKind::Way)),
ElemKind::Relation => (self.rel, ranges.upserts(ElemKind::Relation)),
}
}
}