use crate::common::WkbType;
use crate::error::WkbResult;
use crate::writer::WriteOptions;
use crate::Endianness;
use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
use geo_traits::{CoordTrait, RectTrait};
use std::io::Write;
pub fn rect_wkb_size(geom: &impl RectTrait<T = f64>) -> usize {
let header = 1 + 4 + 4;
let each_coord = geom.dim().size() * 8;
let all_coords = 5 * each_coord;
header + all_coords
}
pub fn write_rect(
writer: &mut impl Write,
geom: &impl RectTrait<T = f64>,
options: &WriteOptions,
) -> WkbResult<()> {
writer.write_u8(options.endianness.into())?;
match options.endianness {
Endianness::LittleEndian => write_rect_content::<LittleEndian>(writer, geom),
Endianness::BigEndian => write_rect_content::<BigEndian>(writer, geom),
}
}
struct Coord {
x: f64,
y: f64,
}
fn write_rect_content<B: ByteOrder>(
writer: &mut impl Write,
geom: &impl RectTrait<T = f64>,
) -> WkbResult<()> {
let wkb_type = WkbType::Polygon(geom.dim().try_into()?);
writer.write_u32::<B>(wkb_type.into())?;
let num_rings = 1;
writer.write_u32::<B>(num_rings)?;
let min_coord = geom.min();
let max_coord = geom.max();
let ll = Coord {
x: min_coord.x(),
y: min_coord.y(),
};
let ul = Coord {
x: min_coord.x(),
y: max_coord.y(),
};
let ur = Coord {
x: max_coord.x(),
y: max_coord.y(),
};
let lr = Coord {
x: max_coord.x(),
y: min_coord.y(),
};
writer.write_f64::<B>(ll.x)?;
writer.write_f64::<B>(ll.y)?;
writer.write_f64::<B>(ul.x)?;
writer.write_f64::<B>(ul.y)?;
writer.write_f64::<B>(ur.x)?;
writer.write_f64::<B>(ur.y)?;
writer.write_f64::<B>(lr.x)?;
writer.write_f64::<B>(lr.y)?;
writer.write_f64::<B>(ll.x)?;
writer.write_f64::<B>(ll.y)?;
Ok(())
}