use crate::backend::default::coordinate::{RealWorldCoordinate, UVCoordinate};
use crate::cityjson::core::coordinate::Coordinate;
use crate::cityjson::core::vertex::{VertexIndex, VertexRef};
use crate::error::{Error, Result};
use std::fmt;
use std::marker::PhantomData;
#[repr(C)]
#[derive(Clone)]
pub struct Vertices<VR: VertexRef, V: Coordinate> {
coordinates: Vec<V>,
_phantom: PhantomData<VR>,
}
impl<VR: VertexRef, V: Coordinate> Vertices<VR, V> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
coordinates: Vec::new(),
_phantom: PhantomData,
}
}
#[inline]
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
coordinates: Vec::with_capacity(capacity),
_phantom: PhantomData,
}
}
#[inline]
pub fn reserve(&mut self, additional_capacity: usize) -> Result<()> {
let max = VR::MAX.try_into().unwrap_or(usize::MAX);
if self.coordinates.len() >= max || self.coordinates.len() + additional_capacity > max {
return Err(Error::VerticesContainerFull {
attempted: self.coordinates.len() + 1,
maximum: max,
});
}
self.coordinates.reserve(additional_capacity);
Ok(())
}
#[must_use]
pub fn len(&self) -> usize {
self.coordinates.len()
}
pub fn push(&mut self, coordinate: V) -> Result<VertexIndex<VR>> {
if self.coordinates.len() >= VR::MAX.try_into().unwrap_or(usize::MAX) {
return Err(Error::VerticesContainerFull {
attempted: self.coordinates.len() + 1,
maximum: VR::MAX.try_into().unwrap_or(usize::MAX),
});
}
let index = VertexIndex::<VR>::try_from(self.coordinates.len())?;
self.coordinates.push(coordinate);
Ok(index)
}
pub fn extend_from_slice(
&mut self,
coordinates: &[V],
) -> Result<std::ops::Range<VertexIndex<VR>>> {
let start = VertexIndex::<VR>::try_from(self.coordinates.len())?;
let maximum = VR::MAX.try_into().unwrap_or(usize::MAX);
let Some(new_len) = self.coordinates.len().checked_add(coordinates.len()) else {
return Err(Error::VerticesContainerFull {
attempted: usize::MAX,
maximum,
});
};
if new_len > maximum {
return Err(Error::VerticesContainerFull {
attempted: new_len,
maximum,
});
}
self.coordinates.reserve(coordinates.len());
self.coordinates.extend_from_slice(coordinates);
let end = VertexIndex::<VR>::try_from(self.coordinates.len())?;
Ok(start..end)
}
#[inline]
pub fn get(&self, index: VertexIndex<VR>) -> Option<&V> {
self.coordinates.get(index.to_usize())
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.coordinates.is_empty()
}
#[inline]
#[must_use]
pub fn as_slice(&self) -> &[V] {
&self.coordinates
}
#[inline]
pub fn clear(&mut self) {
self.coordinates.clear();
}
}
impl<VR: VertexRef, V: Coordinate> fmt::Debug for Vertices<VR, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Vertices")
.field("len", &self.coordinates.len())
.field("capacity", &self.coordinates.capacity())
.field("max_vertices", &VR::MAX.try_into().unwrap_or(usize::MAX))
.finish()
}
}
impl<VR: VertexRef, V: Coordinate> fmt::Display for Vertices<VR, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Vertices[{}/{}]",
self.coordinates.len(),
VR::MAX.try_into().unwrap_or(usize::MAX)
)
}
}
impl<VR: VertexRef, V: Coordinate> Default for Vertices<VR, V> {
fn default() -> Self {
Self::new()
}
}
impl<VR: VertexRef, V: Coordinate> From<Vec<V>> for Vertices<VR, V> {
fn from(value: Vec<V>) -> Self {
Self {
coordinates: value,
_phantom: PhantomData,
}
}
}
impl<VR: VertexRef, V: Coordinate> From<&[V]> for Vertices<VR, V> {
fn from(value: &[V]) -> Self {
Self {
coordinates: Vec::from(value),
_phantom: PhantomData,
}
}
}
pub type GeometryVertices16 = Vertices<u16, RealWorldCoordinate>;
pub type GeometryVertices32 = Vertices<u32, RealWorldCoordinate>;
pub type GeometryVertices64 = Vertices<u64, RealWorldCoordinate>;
pub type UVVertices16 = Vertices<u16, UVCoordinate>;
pub type UVVertices32 = Vertices<u32, UVCoordinate>;
pub type UVVertices64 = Vertices<u64, UVCoordinate>;