use enums::{ByteOrder, OutputDimension};
use crate::{ContextHandle, Geometry, GResult, AsRaw, ContextHandling, ContextInteractions};
use context_handle::PtrWrap;
use geos_sys::*;
use std::sync::Arc;
use error::Error;
use enums::TryFrom;
use c_vec::CVec;
pub struct WKBWriter<'a> {
ptr: PtrWrap<*mut GEOSWKBWriter>,
context: Arc<ContextHandle<'a>>,
}
impl<'a> WKBWriter<'a> {
pub fn new() -> GResult<WKBWriter<'a>> {
match ContextHandle::init_e(Some("WKBWriter::new")) {
Ok(context_handle) => Self::new_with_context(Arc::new(context_handle)),
Err(e) => Err(e),
}
}
pub fn new_with_context(context: Arc<ContextHandle<'a>>) -> GResult<WKBWriter<'a>> {
unsafe {
let ptr = GEOSWKBWriter_create_r(context.as_raw());
WKBWriter::new_from_raw(ptr, context, "new_with_context")
}
}
pub(crate) unsafe fn new_from_raw(
ptr: *mut GEOSWKBWriter,
context: Arc<ContextHandle<'a>>,
caller: &str,
) -> GResult<WKBWriter<'a>> {
if ptr.is_null() {
let extra = if let Some(x) = context.get_last_error() {
format!("\nLast error: {}", x)
} else {
String::new()
};
return Err(Error::NoConstructionFromNullPtr(format!("WKBWriter::{}{}", caller, extra)));
}
Ok(WKBWriter { ptr: PtrWrap(ptr), context })
}
pub fn write_wkb(&self, geometry: &Geometry<'_>) -> GResult<CVec<u8>> {
let mut size = 0;
unsafe {
let ptr = GEOSWKBWriter_write_r(self.get_raw_context(), self.as_raw(),
geometry.as_raw(), &mut size);
if ptr.is_null() {
Err(Error::NoConstructionFromNullPtr(
"WKBWriter::write_wkb failed: GEOSWKBWriter_writeHEX_r returned null pointer".to_owned())
)
} else {
Ok(CVec::new(ptr, size as _))
}
}
}
pub fn write_hex(&self, geometry: &Geometry<'_>) -> GResult<CVec<u8>> {
let mut size = 0;
unsafe {
let ptr = GEOSWKBWriter_writeHEX_r(self.get_raw_context(), self.as_raw(),
geometry.as_raw(), &mut size);
if ptr.is_null() {
Err(Error::NoConstructionFromNullPtr(
"WKBWriter::write_hex failed: GEOSWKBWriter_writeHEX_r returned null pointer".to_owned())
)
} else {
Ok(CVec::new(ptr, size as _))
}
}
}
pub fn set_output_dimension(&mut self, dimension: OutputDimension) {
unsafe {
GEOSWKBWriter_setOutputDimension_r(self.get_raw_context(), self.as_raw(),
dimension.into())
}
}
pub fn get_out_dimension(&self) -> GResult<OutputDimension> {
unsafe {
let out = GEOSWKBWriter_getOutputDimension_r(self.get_raw_context(), self.as_raw());
OutputDimension::try_from(out).map_err(|e| Error::GenericError(e.to_owned()))
}
}
pub fn get_wkb_byte_order(&self) -> GResult<ByteOrder> {
unsafe {
let out = GEOSWKBWriter_getByteOrder_r(self.get_raw_context(), self.as_raw());
ByteOrder::try_from(out).map_err(|e| Error::GenericError(e.to_owned()))
}
}
pub fn set_wkb_byte_order(&mut self, byte_order: ByteOrder) {
unsafe {
GEOSWKBWriter_setByteOrder_r(self.get_raw_context(), self.as_raw(), byte_order.into())
}
}
#[allow(non_snake_case)]
pub fn get_include_SRID(&self) -> GResult<bool> {
unsafe {
let out = GEOSWKBWriter_getIncludeSRID_r(self.get_raw_context(), self.as_raw());
if out < 0 {
Err(Error::GenericError("GEOSWKBWriter_getIncludeSRID_r failed".to_owned()))
} else {
Ok(out != 0)
}
}
}
#[allow(non_snake_case)]
pub fn set_include_SRID(&self, include_SRID: bool) {
unsafe {
GEOSWKBWriter_setIncludeSRID_r(self.get_raw_context(), self.as_raw(), include_SRID as _)
}
}
}
unsafe impl<'a> Send for WKBWriter<'a> {}
unsafe impl<'a> Sync for WKBWriter<'a> {}
impl<'a> Drop for WKBWriter<'a> {
fn drop(&mut self) {
unsafe { GEOSWKBWriter_destroy_r(self.get_raw_context(), self.as_raw()) };
}
}
impl<'a> ContextInteractions<'a> for WKBWriter<'a> {
fn set_context_handle(&mut self, context: ContextHandle<'a>) {
self.context = Arc::new(context);
}
fn get_context_handle(&self) -> &ContextHandle<'a> {
&self.context
}
}
impl<'a> AsRaw for WKBWriter<'a> {
type RawType = *mut GEOSWKBWriter;
fn as_raw(&self) -> Self::RawType {
*self.ptr
}
}
impl<'a> ContextHandling for WKBWriter<'a> {
type Context = Arc<ContextHandle<'a>>;
fn get_raw_context(&self) -> GEOSContextHandle_t {
self.context.as_raw()
}
fn clone_context(&self) -> Arc<ContextHandle<'a>> {
Arc::clone(&self.context)
}
}