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