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: {:?}",
157 dt
158 ))),
159 }
160 }
161}
162
163impl TryFrom<(&dyn Array, &Field)> for WktViewArray {
164 type Error = GeoArrowError;
165
166 fn try_from((arr, field): (&dyn Array, &Field)) -> GeoArrowResult<Self> {
167 let typ = field
168 .try_extension_type::<WktType>()
169 .ok()
170 .unwrap_or_default();
171 (arr, typ).try_into()
172 }
173}
174
175impl<O: OffsetSizeTrait> From<GenericWktArray<O>> for WktViewArray {
176 fn from(value: GenericWktArray<O>) -> Self {
177 let wkb_type = value.data_type;
178 let binary_view_array = value.array;
179
180 let mut builder = StringViewBuilder::new();
182 binary_view_array
183 .iter()
184 .for_each(|value| builder.append_option(value));
185
186 Self {
187 data_type: wkb_type,
188 array: builder.finish(),
189 }
190 }
191}