#![warn(missing_docs)]
use crate::{
MyError,
geom::{XY1V, XY2V, XY3V},
srid::SRID,
wkb::{ByteOrder, Envelope, double, signed},
};
use tracing::error;
#[derive(Debug)]
pub(crate) struct GeoPackageBinaryHeader {
srid: SRID,
envelope: Envelope,
}
impl GeoPackageBinaryHeader {
pub(crate) fn srid(&self) -> &SRID {
&self.srid
}
pub(crate) fn envelope(&self) -> &Envelope {
&self.envelope
}
pub(crate) fn len(&self) -> usize {
2 + 1 + 1 + 4 + 8 * self.envelope.len()
}
pub(crate) fn check_point(&self, xy: &XY1V) -> Result<(), MyError> {
self.envelope.check_point(xy)
}
pub(crate) fn check_line(&self, xy: &[XY1V]) -> Result<(), MyError> {
self.envelope.check_line(xy)
}
pub(crate) fn check_polygon(&self, xy: &[XY2V]) -> Result<(), MyError> {
self.envelope.check_polygon(xy)
}
pub(crate) fn check_points(&self, xy: &[XY1V]) -> Result<(), MyError> {
self.envelope.check_points(xy)
}
pub(crate) fn check_lines(&self, xy: &[XY2V]) -> Result<(), MyError> {
self.envelope.check_lines(xy)
}
pub(crate) fn check_polygons(&self, xy: &[XY3V]) -> Result<(), MyError> {
self.envelope.check_polygons(xy)
}
}
impl TryFrom<&[u8]> for GeoPackageBinaryHeader {
type Error = MyError;
fn try_from(ba: &[u8]) -> Result<Self, Self::Error> {
if ba[..2] != *b"GP" {
let msg = "Input does NOT start w/ expected ('GP') magic";
error!("{msg}");
return Err(MyError::Runtime(msg.into()));
}
let v = ba[2];
if v != 0 {
let msg = format!("Unexpected ({v}) format version");
error!("{msg}");
return Err(MyError::Runtime(msg.into()));
}
let flags = ba[3] & 0x3F;
if flags & 0x20 != 0 {
let msg = "X flag set => NOT StandardGeoPackageBinary";
error!("{msg}");
return Err(MyError::Runtime(msg.into()));
}
if (flags & 0x10) >> 4 == 1 {
let msg = "Y flag set => empty geometry";
error!("{msg}");
return Err(MyError::Runtime(msg.into()));
}
let bo = &ByteOrder::from(flags & 0x01);
let eci = (flags >> 1) & 0x07;
let srs_id = signed(bo, ba, 4)?;
let srid = SRID::try_from(srs_id)?;
let env_len = match eci {
0 => 0,
1 => 4,
2 | 3 => 6,
4 => 8,
x => {
let msg = format!("Invalid ({x}) E flag");
error!("{msg}");
return Err(MyError::Runtime(msg.into()));
}
};
let mut bounds: Vec<f64> = Vec::with_capacity(env_len);
for i in 0..env_len {
let x = double(bo, ba, 8 + i * 8)?;
bounds.push(x);
}
let envelope = Envelope::new(bounds);
Ok(Self { srid, envelope })
}
}