use super::{parse_cartesian_point_inline, EntityDecoder};
impl EntityDecoder<'_> {
#[inline]
pub fn get_entity_ref_list_fast(&mut self, entity_id: u32) -> Option<Vec<u32>> {
let mut ids = Vec::new();
self.get_entity_ref_list_fast_into(entity_id, &mut ids)?;
Some(ids)
}
#[inline]
pub fn get_entity_ref_list_fast_into(&mut self, entity_id: u32, ids: &mut Vec<u32>) -> Option<()> {
ids.clear();
let bytes = self.get_raw_bytes(entity_id)?;
let mut i = 0;
let len = bytes.len();
while i < len && bytes[i] != b'(' {
i += 1;
}
if i >= len {
return None;
}
i += 1;
while i < len && bytes[i] != b'(' {
i += 1;
}
if i >= len {
return None;
}
i += 1;
ids.reserve(32);
while i < len {
while i < len
&& (bytes[i] == b' ' || bytes[i] == b',' || bytes[i] == b'\n' || bytes[i] == b'\r')
{
i += 1;
}
if i >= len || bytes[i] == b')' {
break;
}
if bytes[i] == b'#' {
i += 1;
let start = i;
while i < len && bytes[i].is_ascii_digit() {
i += 1;
}
if i > start {
if let Some(id) = crate::express_id::parse_express_id(&bytes[start..i]) {
ids.push(id);
}
}
} else {
i += 1; }
}
if ids.is_empty() {
None
} else {
Some(())
}
}
#[inline]
pub fn get_polyloop_coords_cached(&mut self, entity_id: u32) -> Option<Vec<(f64, f64, f64)>> {
let mut coords = Vec::new();
self.get_polyloop_coords_cached_into(entity_id, &mut coords)?;
Some(coords)
}
#[inline]
pub fn get_polyloop_coords_cached_into(
&mut self, entity_id: u32, coords: &mut Vec<(f64, f64, f64)>,
) -> Option<()> {
coords.clear();
self.build_index();
let index = self.entity_index.as_ref()?;
let bytes_full = self.content;
let (start, end) = index.lookup(entity_id)?;
let bytes = &bytes_full[start..end];
let mut i = 0;
let len = bytes.len();
while i < len && bytes[i] != b'(' {
i += 1;
}
if i >= len {
return None;
}
i += 1;
while i < len && bytes[i] != b'(' {
i += 1;
}
if i >= len {
return None;
}
i += 1;
coords.reserve(8);
let mut expected_count = 0u32;
while i < len {
while i < len
&& (bytes[i] == b' ' || bytes[i] == b',' || bytes[i] == b'\n' || bytes[i] == b'\r')
{
i += 1;
}
if i >= len || bytes[i] == b')' {
break;
}
if bytes[i] == b'#' {
i += 1;
let id_start = i;
while i < len && bytes[i].is_ascii_digit() {
i += 1;
}
if i > id_start {
expected_count += 1;
if let Some(point_id) =
crate::express_id::parse_express_id(&bytes[id_start..i])
{
if let Some(&coord) = self.point_cache.get(&point_id) {
self.point_cache_hits += 1;
coords.push(coord);
} else {
if let Some((pt_start, pt_end)) = index.lookup(point_id) {
if let Some(coord) =
parse_cartesian_point_inline(&bytes_full[pt_start..pt_end])
{
self.point_cache_misses += 1;
self.point_cache.insert(point_id, coord);
coords.push(coord);
}
}
}
}
}
} else {
i += 1; }
}
if coords.len() >= 3 && coords.len() == expected_count as usize {
Some(())
} else {
coords.clear();
None
}
}
}
#[cfg(test)]
#[path = "fast_buffers_tests.rs"]
mod tests;