use geoarrow_array::{GeoArrowArrayIterator, GeoArrowArrayReader};
use geoarrow_schema::GeoArrowType;
use geoarrow_schema::error::GeoArrowResult;
use pyo3::exceptions::PyValueError;
use pyo3::intern;
use pyo3::prelude::*;
use crate::{PyGeoArray, PyGeoArrayReader, PyGeoArrowResult, PyGeoChunkedArray};
pub enum AnyGeoArray {
Array(PyGeoArray),
Stream(PyGeoArrayReader),
}
impl AnyGeoArray {
pub fn into_chunked_array(self) -> PyGeoArrowResult<PyGeoChunkedArray> {
let reader = self.into_reader()?;
let data_type = reader.data_type();
let chunks = reader.collect::<GeoArrowResult<Vec<_>>>()?;
Ok(PyGeoChunkedArray::try_new(chunks, data_type)?)
}
pub fn into_reader(self) -> PyResult<Box<dyn GeoArrowArrayReader + Send>> {
match self {
Self::Array(array) => {
let geo_array = array.into_inner();
let data_type = geo_array.data_type();
Ok(Box::new(GeoArrowArrayIterator::new(
vec![Ok(geo_array)],
data_type,
)))
}
Self::Stream(stream) => stream.into_reader(),
}
}
pub fn data_type(&self) -> GeoArrowType {
match self {
Self::Array(array) => array.inner().data_type(),
Self::Stream(reader) => reader.data_type().clone(),
}
}
}
impl<'py> FromPyObject<'_, 'py> for AnyGeoArray {
type Error = PyErr;
fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
if ob.hasattr(intern!(ob.py(), "__arrow_c_array__"))? {
Ok(Self::Array(ob.extract()?))
} else if ob.hasattr(intern!(ob.py(), "__arrow_c_stream__"))? {
Ok(Self::Stream(ob.extract()?))
} else {
Err(PyValueError::new_err(
"Expected object with __arrow_c_array__ or __arrow_c_stream__ method.",
))
}
}
}