use std::io::Cursor;
use crate::common::Dimension;
use crate::reader::util::ReadBytesExt;
use crate::Endianness;
use geo_traits::{CoordTrait, Dimensions};
const F64_WIDTH: u64 = 8;
#[derive(Debug, Clone, Copy)]
pub struct Coord<'a> {
buf: &'a [u8],
byte_order: Endianness,
dim: Dimension,
}
impl<'a> Coord<'a> {
pub(crate) fn new(buf: &'a [u8], byte_order: Endianness, dim: Dimension) -> Self {
Self {
buf: &buf[..dim.size() * F64_WIDTH as usize],
byte_order,
dim,
}
}
#[inline]
fn get_x(&self) -> f64 {
let mut reader = Cursor::new(self.buf);
reader.read_f64(self.byte_order).unwrap()
}
#[inline]
fn get_y(&self) -> f64 {
let mut reader = Cursor::new(self.buf);
reader.set_position(F64_WIDTH);
reader.read_f64(self.byte_order).unwrap()
}
#[inline]
fn get_nth_unchecked(&self, n: usize) -> f64 {
debug_assert!(n < self.dim.size());
let mut reader = Cursor::new(self.buf);
reader.set_position(n as u64 * F64_WIDTH);
reader.read_f64(self.byte_order).unwrap()
}
#[inline]
pub fn byte_order(&self) -> Endianness {
self.byte_order
}
#[inline]
pub fn coord_slice(&self) -> &'a [u8] {
let end = self.size() as usize;
&self.buf[0..end]
}
#[inline]
pub fn dimension(&self) -> Dimension {
self.dim
}
#[inline]
pub fn size(&self) -> u64 {
self.buf.len() as u64
}
}
impl CoordTrait for Coord<'_> {
type T = f64;
fn dim(&self) -> Dimensions {
self.dim.into()
}
#[inline]
fn nth_or_panic(&self, n: usize) -> Self::T {
self.get_nth_unchecked(n)
}
#[inline]
fn x(&self) -> Self::T {
self.get_x()
}
#[inline]
fn y(&self) -> Self::T {
self.get_y()
}
}