geoarrow_array/array/
wkb_view.rs
1use std::sync::Arc;
2
3use arrow_array::builder::BinaryViewBuilder;
4use arrow_array::cast::AsArray;
5use arrow_array::{Array, ArrayRef, BinaryViewArray, OffsetSizeTrait};
6use arrow_buffer::NullBuffer;
7use arrow_schema::{DataType, Field};
8use geoarrow_schema::error::{GeoArrowError, GeoArrowResult};
9use geoarrow_schema::{GeoArrowType, Metadata, WkbType};
10use wkb::reader::Wkb;
11
12use crate::array::GenericWkbArray;
13use crate::{GeoArrowArray, GeoArrowArrayAccessor, IntoArrow};
14
15#[derive(Debug, Clone, PartialEq)]
22pub struct WkbViewArray {
23 pub(crate) data_type: WkbType,
24 pub(crate) array: BinaryViewArray,
25}
26
27impl WkbViewArray {
28 pub fn new(array: BinaryViewArray, metadata: Arc<Metadata>) -> Self {
30 Self {
31 data_type: WkbType::new(metadata),
32 array,
33 }
34 }
35
36 pub fn is_empty(&self) -> bool {
38 self.len() == 0
39 }
40
41 #[inline]
47 pub fn slice(&self, offset: usize, length: usize) -> Self {
48 assert!(
49 offset + length <= self.len(),
50 "offset + length may not exceed length of array"
51 );
52 Self {
53 array: self.array.slice(offset, length),
54 data_type: self.data_type.clone(),
55 }
56 }
57
58 pub fn with_metadata(&self, metadata: Arc<Metadata>) -> Self {
60 let mut arr = self.clone();
61 arr.data_type = self.data_type.clone().with_metadata(metadata);
62 arr
63 }
64}
65
66impl GeoArrowArray for WkbViewArray {
67 fn as_any(&self) -> &dyn std::any::Any {
68 self
69 }
70
71 fn into_array_ref(self) -> ArrayRef {
72 Arc::new(self.into_arrow())
73 }
74
75 fn to_array_ref(&self) -> ArrayRef {
76 self.clone().into_array_ref()
77 }
78
79 #[inline]
80 fn len(&self) -> usize {
81 self.array.len()
82 }
83
84 #[inline]
85 fn logical_nulls(&self) -> Option<NullBuffer> {
86 self.array.logical_nulls()
87 }
88
89 #[inline]
90 fn logical_null_count(&self) -> usize {
91 self.array.logical_null_count()
92 }
93
94 #[inline]
95 fn is_null(&self, i: usize) -> bool {
96 self.array.is_null(i)
97 }
98
99 fn data_type(&self) -> GeoArrowType {
100 GeoArrowType::WkbView(self.data_type.clone())
101 }
102
103 fn slice(&self, offset: usize, length: usize) -> Arc<dyn GeoArrowArray> {
104 Arc::new(self.slice(offset, length))
105 }
106
107 fn with_metadata(self, metadata: Arc<Metadata>) -> Arc<dyn GeoArrowArray> {
108 Arc::new(Self::with_metadata(&self, metadata))
109 }
110}
111
112impl<'a> GeoArrowArrayAccessor<'a> for WkbViewArray {
113 type Item = Wkb<'a>;
114
115 unsafe fn value_unchecked(&'a self, index: usize) -> GeoArrowResult<Self::Item> {
116 let buf = self.array.value(index);
117 Wkb::try_new(buf).map_err(|err| GeoArrowError::External(Box::new(err)))
118 }
119}
120
121impl IntoArrow for WkbViewArray {
122 type ArrowArray = BinaryViewArray;
123 type ExtensionType = WkbType;
124
125 fn into_arrow(self) -> Self::ArrowArray {
126 self.array
127 }
128
129 fn extension_type(&self) -> &Self::ExtensionType {
130 &self.data_type
131 }
132}
133
134impl From<(BinaryViewArray, WkbType)> for WkbViewArray {
135 fn from((value, typ): (BinaryViewArray, WkbType)) -> Self {
136 Self {
137 data_type: typ,
138 array: value,
139 }
140 }
141}
142
143impl TryFrom<(&dyn Array, WkbType)> for WkbViewArray {
144 type Error = GeoArrowError;
145
146 fn try_from((value, typ): (&dyn Array, WkbType)) -> GeoArrowResult<Self> {
147 match value.data_type() {
148 DataType::BinaryView => Ok((value.as_binary_view().clone(), typ).into()),
149 dt => Err(GeoArrowError::InvalidGeoArrow(format!(
150 "Unexpected WkbView DataType: {:?}",
151 dt
152 ))),
153 }
154 }
155}
156
157impl TryFrom<(&dyn Array, &Field)> for WkbViewArray {
158 type Error = GeoArrowError;
159
160 fn try_from((arr, field): (&dyn Array, &Field)) -> GeoArrowResult<Self> {
161 let typ = field
162 .try_extension_type::<WkbType>()
163 .ok()
164 .unwrap_or_default();
165 (arr, typ).try_into()
166 }
167}
168
169impl<O: OffsetSizeTrait> From<GenericWkbArray<O>> for WkbViewArray {
170 fn from(value: GenericWkbArray<O>) -> Self {
171 let wkb_type = value.data_type;
172 let binary_view_array = value.array;
173
174 let mut builder = BinaryViewBuilder::new();
176 binary_view_array
177 .iter()
178 .for_each(|value| builder.append_option(value));
179
180 Self {
181 data_type: wkb_type,
182 array: builder.finish(),
183 }
184 }
185}