1use std::sync::Arc;
5
6use arrow_array::OffsetSizeTrait;
7use arrow_array::builder::{
8 BinaryViewBuilder, GenericByteBuilder, GenericStringBuilder, StringViewBuilder,
9};
10use arrow_array::cast::AsArray;
11use geoarrow_schema::error::{GeoArrowError, GeoArrowResult};
12use geoarrow_schema::{GeoArrowType, WkbType};
13use wkb::Endianness;
14use wkb::writer::WriteOptions;
15
16use crate::array::*;
17use crate::builder::{
18 GeometryBuilder, GeometryCollectionBuilder, LineStringBuilder, MultiLineStringBuilder,
19 MultiPointBuilder, MultiPolygonBuilder, PointBuilder, PolygonBuilder, WkbBuilder,
20};
21use crate::trait_::GeoArrowArray;
22use crate::{GeoArrowArrayAccessor, IntoArrow};
23
24pub trait AsGeoArrowArray {
53 fn as_point_opt(&self) -> Option<&PointArray>;
55
56 #[inline]
58 fn as_point(&self) -> &PointArray {
59 self.as_point_opt().unwrap()
60 }
61
62 fn as_line_string_opt(&self) -> Option<&LineStringArray>;
64
65 #[inline]
67 fn as_line_string(&self) -> &LineStringArray {
68 self.as_line_string_opt().unwrap()
69 }
70
71 fn as_polygon_opt(&self) -> Option<&PolygonArray>;
73
74 #[inline]
76 fn as_polygon(&self) -> &PolygonArray {
77 self.as_polygon_opt().unwrap()
78 }
79
80 fn as_multi_point_opt(&self) -> Option<&MultiPointArray>;
82
83 #[inline]
85 fn as_multi_point(&self) -> &MultiPointArray {
86 self.as_multi_point_opt().unwrap()
87 }
88
89 fn as_multi_line_string_opt(&self) -> Option<&MultiLineStringArray>;
92
93 #[inline]
95 fn as_multi_line_string(&self) -> &MultiLineStringArray {
96 self.as_multi_line_string_opt().unwrap()
97 }
98
99 fn as_multi_polygon_opt(&self) -> Option<&MultiPolygonArray>;
102
103 #[inline]
105 fn as_multi_polygon(&self) -> &MultiPolygonArray {
106 self.as_multi_polygon_opt().unwrap()
107 }
108
109 fn as_geometry_collection_opt(&self) -> Option<&GeometryCollectionArray>;
112
113 #[inline]
115 fn as_geometry_collection(&self) -> &GeometryCollectionArray {
116 self.as_geometry_collection_opt().unwrap()
117 }
118
119 fn as_rect_opt(&self) -> Option<&RectArray>;
121
122 #[inline]
124 fn as_rect(&self) -> &RectArray {
125 self.as_rect_opt().unwrap()
126 }
127
128 fn as_geometry_opt(&self) -> Option<&GeometryArray>;
130
131 #[inline]
133 fn as_geometry(&self) -> &GeometryArray {
134 self.as_geometry_opt().unwrap()
135 }
136
137 fn as_wkb_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericWkbArray<O>>;
139
140 #[inline]
142 fn as_wkb<O: OffsetSizeTrait>(&self) -> &GenericWkbArray<O> {
143 self.as_wkb_opt::<O>().unwrap()
144 }
145
146 fn as_wkb_view_opt(&self) -> Option<&WkbViewArray>;
148
149 #[inline]
151 fn as_wkb_view(&self) -> &WkbViewArray {
152 self.as_wkb_view_opt().unwrap()
153 }
154
155 fn as_wkt_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericWktArray<O>>;
157
158 #[inline]
160 fn as_wkt<O: OffsetSizeTrait>(&self) -> &GenericWktArray<O> {
161 self.as_wkt_opt::<O>().unwrap()
162 }
163
164 fn as_wkt_view_opt(&self) -> Option<&WktViewArray>;
166
167 #[inline]
169 fn as_wkt_view(&self) -> &WktViewArray {
170 self.as_wkt_view_opt().unwrap()
171 }
172}
173
174impl AsGeoArrowArray for dyn GeoArrowArray + '_ {
176 #[inline]
177 fn as_point_opt(&self) -> Option<&PointArray> {
178 self.as_any().downcast_ref::<PointArray>()
179 }
180
181 #[inline]
182 fn as_line_string_opt(&self) -> Option<&LineStringArray> {
183 self.as_any().downcast_ref::<LineStringArray>()
184 }
185
186 #[inline]
187 fn as_polygon_opt(&self) -> Option<&PolygonArray> {
188 self.as_any().downcast_ref::<PolygonArray>()
189 }
190
191 #[inline]
192 fn as_multi_point_opt(&self) -> Option<&MultiPointArray> {
193 self.as_any().downcast_ref::<MultiPointArray>()
194 }
195
196 #[inline]
197 fn as_multi_line_string_opt(&self) -> Option<&MultiLineStringArray> {
198 self.as_any().downcast_ref::<MultiLineStringArray>()
199 }
200
201 #[inline]
202 fn as_multi_polygon_opt(&self) -> Option<&MultiPolygonArray> {
203 self.as_any().downcast_ref::<MultiPolygonArray>()
204 }
205
206 #[inline]
207 fn as_geometry_collection_opt(&self) -> Option<&GeometryCollectionArray> {
208 self.as_any().downcast_ref::<GeometryCollectionArray>()
209 }
210
211 #[inline]
212 fn as_rect_opt(&self) -> Option<&RectArray> {
213 self.as_any().downcast_ref::<RectArray>()
214 }
215
216 #[inline]
217 fn as_geometry_opt(&self) -> Option<&GeometryArray> {
218 self.as_any().downcast_ref::<GeometryArray>()
219 }
220
221 #[inline]
222 fn as_wkb_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericWkbArray<O>> {
223 self.as_any().downcast_ref::<GenericWkbArray<O>>()
224 }
225
226 #[inline]
227 fn as_wkb_view_opt(&self) -> Option<&WkbViewArray> {
228 self.as_any().downcast_ref::<WkbViewArray>()
229 }
230
231 #[inline]
232 fn as_wkt_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericWktArray<O>> {
233 self.as_any().downcast_ref::<GenericWktArray<O>>()
234 }
235
236 #[inline]
237 fn as_wkt_view_opt(&self) -> Option<&WktViewArray> {
238 self.as_any().downcast_ref::<WktViewArray>()
239 }
240}
241
242impl AsGeoArrowArray for Arc<dyn GeoArrowArray> {
243 #[inline]
244 fn as_point_opt(&self) -> Option<&PointArray> {
245 self.as_any().downcast_ref::<PointArray>()
246 }
247
248 #[inline]
249 fn as_line_string_opt(&self) -> Option<&LineStringArray> {
250 self.as_any().downcast_ref::<LineStringArray>()
251 }
252
253 #[inline]
254 fn as_polygon_opt(&self) -> Option<&PolygonArray> {
255 self.as_any().downcast_ref::<PolygonArray>()
256 }
257
258 #[inline]
259 fn as_multi_point_opt(&self) -> Option<&MultiPointArray> {
260 self.as_any().downcast_ref::<MultiPointArray>()
261 }
262
263 #[inline]
264 fn as_multi_line_string_opt(&self) -> Option<&MultiLineStringArray> {
265 self.as_any().downcast_ref::<MultiLineStringArray>()
266 }
267
268 #[inline]
269 fn as_multi_polygon_opt(&self) -> Option<&MultiPolygonArray> {
270 self.as_any().downcast_ref::<MultiPolygonArray>()
271 }
272
273 #[inline]
274 fn as_geometry_collection_opt(&self) -> Option<&GeometryCollectionArray> {
275 self.as_any().downcast_ref::<GeometryCollectionArray>()
276 }
277
278 #[inline]
279 fn as_rect_opt(&self) -> Option<&RectArray> {
280 self.as_any().downcast_ref::<RectArray>()
281 }
282
283 #[inline]
284 fn as_geometry_opt(&self) -> Option<&GeometryArray> {
285 self.as_any().downcast_ref::<GeometryArray>()
286 }
287
288 #[inline]
289 fn as_wkb_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericWkbArray<O>> {
290 self.as_any().downcast_ref::<GenericWkbArray<O>>()
291 }
292
293 #[inline]
294 fn as_wkb_view_opt(&self) -> Option<&WkbViewArray> {
295 self.as_any().downcast_ref::<WkbViewArray>()
296 }
297
298 #[inline]
299 fn as_wkt_opt<O: OffsetSizeTrait>(&self) -> Option<&GenericWktArray<O>> {
300 self.as_any().downcast_ref::<GenericWktArray<O>>()
301 }
302
303 #[inline]
304 fn as_wkt_view_opt(&self) -> Option<&WktViewArray> {
305 self.as_any().downcast_ref::<WktViewArray>()
306 }
307}
308
309pub fn to_wkb<O: OffsetSizeTrait>(arr: &dyn GeoArrowArray) -> GeoArrowResult<GenericWkbArray<O>> {
311 use GeoArrowType::*;
312 match arr.data_type() {
313 Point(_) => impl_to_wkb(arr.as_point()),
314 LineString(_) => impl_to_wkb(arr.as_line_string()),
315 Polygon(_) => impl_to_wkb(arr.as_polygon()),
316 MultiPoint(_) => impl_to_wkb(arr.as_multi_point()),
317 MultiLineString(_) => impl_to_wkb(arr.as_multi_line_string()),
318 MultiPolygon(_) => impl_to_wkb(arr.as_multi_polygon()),
319 Geometry(_) => impl_to_wkb(arr.as_geometry()),
320 GeometryCollection(_) => impl_to_wkb(arr.as_geometry_collection()),
321 Rect(_) => impl_to_wkb(arr.as_rect()),
322 Wkb(typ) => {
323 if O::IS_LARGE {
325 let large_arr: GenericWkbArray<i64> = arr.as_wkb::<i32>().clone().into();
327 let array = large_arr.to_array_ref().as_binary::<O>().clone();
328 Ok(GenericWkbArray::new(array, typ.metadata().clone()))
329 } else {
330 let array = arr.as_wkb::<i32>().to_array_ref();
333 let array = array.as_binary::<O>().clone();
334 Ok(GenericWkbArray::new(array, typ.metadata().clone()))
335 }
336 }
337 LargeWkb(typ) => {
338 if O::IS_LARGE {
339 let array = arr.as_wkb::<i64>().to_array_ref();
342 let array = array.as_binary::<O>().clone();
343 Ok(GenericWkbArray::new(array, typ.metadata().clone()))
344 } else {
345 let small_arr: GenericWkbArray<i32> = arr.as_wkb::<i64>().clone().try_into()?;
347 let array = small_arr.to_array_ref().as_binary::<O>().clone();
348 Ok(GenericWkbArray::new(array, typ.metadata().clone()))
349 }
350 }
351 WkbView(_) => {
352 let wkb_view_arr = arr.as_wkb_view();
353 let metadata = wkb_view_arr.data_type().metadata().clone();
354 let array = wkb_view_arr.clone().into_arrow();
355
356 let mut builder = GenericByteBuilder::with_capacity(arr.len(), 0);
357 array.iter().for_each(|value| builder.append_option(value));
358 Ok(GenericWkbArray::new(builder.finish(), metadata))
359 }
360 Wkt(_) => impl_to_wkb(arr.as_wkt::<i32>()),
361 LargeWkt(_) => impl_to_wkb(arr.as_wkt::<i64>()),
362 WktView(_) => impl_to_wkb(arr.as_wkt_view()),
363 }
364}
365
366fn impl_to_wkb<'a, O: OffsetSizeTrait>(
367 geo_arr: &'a impl GeoArrowArrayAccessor<'a>,
368) -> GeoArrowResult<GenericWkbArray<O>> {
369 let geoms = geo_arr
370 .iter()
371 .map(|x| x.transpose())
372 .collect::<GeoArrowResult<Vec<_>>>()?;
373 let wkb_type = WkbType::new(geo_arr.data_type().metadata().clone());
374 Ok(WkbBuilder::from_nullable_geometries(geoms.as_slice(), wkb_type)?.finish())
375}
376
377pub fn to_wkb_view(arr: &dyn GeoArrowArray) -> GeoArrowResult<WkbViewArray> {
379 use GeoArrowType::*;
380 match arr.data_type() {
381 Point(_) => impl_to_wkb_view(arr.as_point()),
382 LineString(_) => impl_to_wkb_view(arr.as_line_string()),
383 Polygon(_) => impl_to_wkb_view(arr.as_polygon()),
384 MultiPoint(_) => impl_to_wkb_view(arr.as_multi_point()),
385 MultiLineString(_) => impl_to_wkb_view(arr.as_multi_line_string()),
386 MultiPolygon(_) => impl_to_wkb_view(arr.as_multi_polygon()),
387 Geometry(_) => impl_to_wkb_view(arr.as_geometry()),
388 GeometryCollection(_) => impl_to_wkb_view(arr.as_geometry_collection()),
389 Rect(_) => impl_to_wkb_view(arr.as_rect()),
390 Wkb(_) => wkb_array_to_wkb_view(arr.as_wkb::<i32>()),
391 LargeWkb(_) => wkb_array_to_wkb_view(arr.as_wkb::<i64>()),
392 WkbView(_) => Ok(arr.as_wkb_view().clone()),
393 Wkt(_) => impl_to_wkb_view(arr.as_wkt::<i32>()),
394 LargeWkt(_) => impl_to_wkb_view(arr.as_wkt::<i64>()),
395 WktView(_) => impl_to_wkb_view(arr.as_wkt_view()),
396 }
397}
398
399fn impl_to_wkb_view<'a>(
403 geo_arr: &'a impl GeoArrowArrayAccessor<'a>,
404) -> GeoArrowResult<WkbViewArray> {
405 let geoms = geo_arr
406 .iter()
407 .map(|x| x.transpose())
408 .collect::<GeoArrowResult<Vec<_>>>()?;
409
410 let mut builder = BinaryViewBuilder::with_capacity(geo_arr.len());
411 let wkb_options = WriteOptions {
412 endianness: Endianness::LittleEndian,
413 };
414 for maybe_geom in geoms {
415 if let Some(geom) = maybe_geom {
416 let mut buf = Vec::new();
417 wkb::writer::write_geometry(&mut buf, &geom, &wkb_options).unwrap();
418 builder.append_value(buf);
419 } else {
420 builder.append_null();
421 }
422 }
423
424 let binary_view_arr = builder.finish();
425 Ok(WkbViewArray::new(
426 binary_view_arr,
427 geo_arr.data_type().metadata().clone(),
428 ))
429}
430
431fn wkb_array_to_wkb_view<O: OffsetSizeTrait>(
433 arr: &GenericWkbArray<O>,
434) -> GeoArrowResult<WkbViewArray> {
435 let metadata = arr.data_type().metadata().clone();
436 let mut builder = BinaryViewBuilder::with_capacity(arr.len());
437
438 for value in arr.inner().iter() {
439 if let Some(bytes) = value {
440 builder.append_value(bytes);
441 } else {
442 builder.append_null();
443 }
444 }
445
446 Ok(WkbViewArray::new(builder.finish(), metadata))
447}
448
449pub fn from_wkb<'a, A: GenericWkbArrayType<'a>>(
458 arr: &'a A,
459 to_type: GeoArrowType,
460) -> GeoArrowResult<Arc<dyn GeoArrowArray>> {
461 let geoms = arr
462 .iter()
463 .map(|g| g.transpose())
464 .collect::<GeoArrowResult<Vec<_>>>()?;
465
466 use GeoArrowType::*;
467 let result: Arc<dyn GeoArrowArray> = match to_type {
468 Point(typ) => Arc::new(PointBuilder::from_nullable_geometries(&geoms, typ)?.finish()),
469 LineString(typ) => {
470 Arc::new(LineStringBuilder::from_nullable_geometries(&geoms, typ)?.finish())
471 }
472 Polygon(typ) => Arc::new(PolygonBuilder::from_nullable_geometries(&geoms, typ)?.finish()),
473 MultiPoint(typ) => {
474 Arc::new(MultiPointBuilder::from_nullable_geometries(&geoms, typ)?.finish())
475 }
476 MultiLineString(typ) => {
477 Arc::new(MultiLineStringBuilder::from_nullable_geometries(&geoms, typ)?.finish())
478 }
479 MultiPolygon(typ) => {
480 Arc::new(MultiPolygonBuilder::from_nullable_geometries(&geoms, typ)?.finish())
481 }
482 GeometryCollection(typ) => {
483 Arc::new(GeometryCollectionBuilder::from_nullable_geometries(&geoms, typ)?.finish())
484 }
485 Rect(_) => {
486 return Err(GeoArrowError::IncorrectGeometryType(format!(
487 "Cannot decode WKB geometries to Rect geometry type in from_wkb {to_type:?}",
488 )));
489 }
490 Geometry(typ) => Arc::new(GeometryBuilder::from_nullable_geometries(&geoms, typ)?.finish()),
491 Wkb(typ) => {
492 let mut wkb_arr = to_wkb::<i32>(arr)?;
493 wkb_arr.data_type = typ;
494 Arc::new(wkb_arr)
495 }
496 LargeWkb(typ) => {
497 let mut wkb_arr = to_wkb::<i64>(arr)?;
498 wkb_arr.data_type = typ;
499 Arc::new(wkb_arr)
500 }
501 WkbView(typ) => {
502 let mut wkb_view_arr = to_wkb_view(arr)?;
503 wkb_view_arr.data_type = typ;
504 Arc::new(wkb_view_arr)
505 }
506 Wkt(typ) => {
507 let mut wkt_arr = to_wkt::<i32>(arr)?;
508 wkt_arr.data_type = typ;
509 Arc::new(wkt_arr)
510 }
511 LargeWkt(typ) => {
512 let mut wkt_arr = to_wkt::<i64>(arr)?;
513 wkt_arr.data_type = typ;
514 Arc::new(wkt_arr)
515 }
516 WktView(typ) => {
517 let mut wkt_view_arr = to_wkt_view(arr)?;
518 wkt_view_arr.data_type = typ;
519 Arc::new(wkt_view_arr)
520 }
521 };
522 Ok(result)
523}
524
525pub fn to_wkt<O: OffsetSizeTrait>(arr: &dyn GeoArrowArray) -> GeoArrowResult<GenericWktArray<O>> {
527 use GeoArrowType::*;
528 match arr.data_type() {
529 Point(_) => impl_to_wkt(arr.as_point()),
530 LineString(_) => impl_to_wkt(arr.as_line_string()),
531 Polygon(_) => impl_to_wkt(arr.as_polygon()),
532 MultiPoint(_) => impl_to_wkt(arr.as_multi_point()),
533 MultiLineString(_) => impl_to_wkt(arr.as_multi_line_string()),
534 MultiPolygon(_) => impl_to_wkt(arr.as_multi_polygon()),
535 Geometry(_) => impl_to_wkt(arr.as_geometry()),
536 GeometryCollection(_) => impl_to_wkt(arr.as_geometry_collection()),
537 Rect(_) => impl_to_wkt(arr.as_rect()),
538 Wkb(_) => impl_to_wkt(arr.as_wkb::<i32>()),
539 LargeWkb(_) => impl_to_wkt(arr.as_wkb::<i64>()),
540 WkbView(_) => impl_to_wkt(arr.as_wkb_view()),
541 Wkt(typ) => {
542 if O::IS_LARGE {
543 let large_arr: GenericWktArray<i64> = arr.as_wkt::<i32>().clone().into();
544 let array = large_arr.to_array_ref().as_string::<O>().clone();
545 Ok(GenericWktArray::new(array, typ.metadata().clone()))
546 } else {
547 let array = arr.as_wkt::<i32>().to_array_ref();
550 let array = array.as_string::<O>().clone();
551 Ok(GenericWktArray::new(array, typ.metadata().clone()))
552 }
553 }
554 LargeWkt(typ) => {
555 if O::IS_LARGE {
556 let array = arr.as_wkt::<i64>().to_array_ref();
559 let array = array.as_string::<O>().clone();
560 Ok(GenericWktArray::new(array, typ.metadata().clone()))
561 } else {
562 let small_arr: GenericWktArray<i32> = arr.as_wkt::<i64>().clone().try_into()?;
563 let array = small_arr.to_array_ref().as_string::<O>().clone();
564 Ok(GenericWktArray::new(array, typ.metadata().clone()))
565 }
566 }
567 WktView(_) => {
568 let wkt_view_arr = arr.as_wkt_view();
569 let metadata = wkt_view_arr.data_type().metadata().clone();
570 let array = wkt_view_arr.clone().into_arrow();
571
572 let mut builder = GenericStringBuilder::with_capacity(arr.len(), 0);
573 array.iter().for_each(|value| builder.append_option(value));
574 Ok(GenericWktArray::new(builder.finish(), metadata))
575 }
576 }
577}
578
579fn impl_to_wkt<'a, O: OffsetSizeTrait>(
580 geo_arr: &'a impl GeoArrowArrayAccessor<'a>,
581) -> GeoArrowResult<GenericWktArray<O>> {
582 let metadata = geo_arr.data_type().metadata().clone();
583 let mut builder = GenericStringBuilder::with_capacity(geo_arr.len(), 0);
584
585 for maybe_geom in geo_arr.iter() {
586 if let Some(geom) = maybe_geom {
587 wkt::to_wkt::write_geometry(&mut builder, &geom?)
588 .map_err(|err| GeoArrowError::External(Box::new(err)))?;
589 builder.append_value("");
590 } else {
591 builder.append_null();
592 }
593 }
594
595 Ok(GenericWktArray::new(builder.finish(), metadata))
596}
597
598pub fn to_wkt_view(arr: &dyn GeoArrowArray) -> GeoArrowResult<WktViewArray> {
600 use GeoArrowType::*;
601 match arr.data_type() {
602 Point(_) => impl_to_wkt_view(arr.as_point()),
603 LineString(_) => impl_to_wkt_view(arr.as_line_string()),
604 Polygon(_) => impl_to_wkt_view(arr.as_polygon()),
605 MultiPoint(_) => impl_to_wkt_view(arr.as_multi_point()),
606 MultiLineString(_) => impl_to_wkt_view(arr.as_multi_line_string()),
607 MultiPolygon(_) => impl_to_wkt_view(arr.as_multi_polygon()),
608 Geometry(_) => impl_to_wkt_view(arr.as_geometry()),
609 GeometryCollection(_) => impl_to_wkt_view(arr.as_geometry_collection()),
610 Rect(_) => impl_to_wkt_view(arr.as_rect()),
611 Wkb(_) => impl_to_wkt_view(arr.as_wkb::<i32>()),
612 LargeWkb(_) => impl_to_wkt_view(arr.as_wkb::<i64>()),
613 WkbView(_) => impl_to_wkt_view(arr.as_wkb_view()),
614 Wkt(_) => wkt_array_to_wkt_view(arr.as_wkt::<i32>()),
615 LargeWkt(_) => wkt_array_to_wkt_view(arr.as_wkt::<i64>()),
616 WktView(_) => Ok(arr.as_wkt_view().clone()),
617 }
618}
619
620fn impl_to_wkt_view<'a>(
624 geo_arr: &'a impl GeoArrowArrayAccessor<'a>,
625) -> GeoArrowResult<WktViewArray> {
626 let metadata = geo_arr.data_type().metadata().clone();
627 let mut builder = StringViewBuilder::with_capacity(geo_arr.len());
628
629 for maybe_geom in geo_arr.iter() {
630 if let Some(geom) = maybe_geom {
631 let mut s = String::new();
632 wkt::to_wkt::write_geometry(&mut s, &geom?)
633 .map_err(|err| GeoArrowError::External(Box::new(err)))?;
634 builder.append_value(s);
635 } else {
636 builder.append_null();
637 }
638 }
639
640 Ok(WktViewArray::new(builder.finish(), metadata))
641}
642
643fn wkt_array_to_wkt_view<O: OffsetSizeTrait>(
645 arr: &GenericWktArray<O>,
646) -> GeoArrowResult<WktViewArray> {
647 let metadata = arr.data_type().metadata().clone();
648 let mut builder = StringViewBuilder::with_capacity(arr.len());
649
650 for value in arr.inner().iter() {
651 if let Some(s) = value {
652 builder.append_value(s);
653 } else {
654 builder.append_null();
655 }
656 }
657
658 Ok(WktViewArray::new(builder.finish(), metadata))
659}
660
661pub fn from_wkt<A: GenericWktArrayType>(
667 arr: &A,
668 to_type: GeoArrowType,
669) -> GeoArrowResult<Arc<dyn GeoArrowArray>> {
670 let geoms = arr
671 .iter()
672 .map(|g| g.transpose())
673 .collect::<GeoArrowResult<Vec<_>>>()?;
674
675 use GeoArrowType::*;
676 let result: Arc<dyn GeoArrowArray> = match to_type {
677 Point(typ) => Arc::new(PointBuilder::from_nullable_geometries(&geoms, typ)?.finish()),
678 LineString(typ) => {
679 Arc::new(LineStringBuilder::from_nullable_geometries(&geoms, typ)?.finish())
680 }
681 Polygon(typ) => Arc::new(PolygonBuilder::from_nullable_geometries(&geoms, typ)?.finish()),
682 MultiPoint(typ) => {
683 Arc::new(MultiPointBuilder::from_nullable_geometries(&geoms, typ)?.finish())
684 }
685 MultiLineString(typ) => {
686 Arc::new(MultiLineStringBuilder::from_nullable_geometries(&geoms, typ)?.finish())
687 }
688 MultiPolygon(typ) => {
689 Arc::new(MultiPolygonBuilder::from_nullable_geometries(&geoms, typ)?.finish())
690 }
691 GeometryCollection(typ) => {
692 Arc::new(GeometryCollectionBuilder::from_nullable_geometries(&geoms, typ)?.finish())
693 }
694 Rect(_) => {
695 return Err(GeoArrowError::IncorrectGeometryType(format!(
696 "Cannot decode WKT geometries to Rect geometry type in from_wkt {to_type:?}",
697 )));
698 }
699 Geometry(typ) => Arc::new(GeometryBuilder::from_nullable_geometries(&geoms, typ)?.finish()),
700 Wkb(typ) => {
701 let mut wkb_arr = to_wkb::<i32>(arr)?;
702 wkb_arr.data_type = typ;
703 Arc::new(wkb_arr)
704 }
705 LargeWkb(typ) => {
706 let mut wkb_arr = to_wkb::<i64>(arr)?;
707 wkb_arr.data_type = typ;
708 Arc::new(wkb_arr)
709 }
710 WkbView(typ) => {
711 let mut wkb_view_arr = to_wkb_view(arr)?;
712 wkb_view_arr.data_type = typ;
713 Arc::new(wkb_view_arr)
714 }
715 Wkt(typ) => {
716 let mut wkt_arr = to_wkt::<i32>(arr)?;
717 wkt_arr.data_type = typ;
718 Arc::new(wkt_arr)
719 }
720 LargeWkt(typ) => {
721 let mut wkt_arr = to_wkt::<i64>(arr)?;
722 wkt_arr.data_type = typ;
723 Arc::new(wkt_arr)
724 }
725 WktView(typ) => {
726 let mut wkt_view_arr = to_wkt_view(arr)?;
727 wkt_view_arr.data_type = typ;
728 Arc::new(wkt_view_arr)
729 }
730 };
731 Ok(result)
732}
733
734#[doc(hidden)]
738pub mod __private {
739 pub use geoarrow_schema::GeoArrowType;
740}
741
742#[macro_export]
819macro_rules! downcast_geoarrow_array {
820 ($array:ident, $fn:expr $(, $args:expr )* $(,)?) => {
821 match $array.data_type() {
822 $crate::cast::__private::GeoArrowType::Point(_) => {
823 $fn($crate::cast::AsGeoArrowArray::as_point($array) $(, $args )*)
824 }
825 $crate::cast::__private::GeoArrowType::LineString(_) => {
826 $fn($crate::cast::AsGeoArrowArray::as_line_string($array) $(, $args )*)
827 }
828 $crate::cast::__private::GeoArrowType::Polygon(_) => {
829 $fn($crate::cast::AsGeoArrowArray::as_polygon($array) $(, $args )*)
830 }
831 $crate::cast::__private::GeoArrowType::MultiPoint(_) => {
832 $fn($crate::cast::AsGeoArrowArray::as_multi_point($array) $(, $args )*)
833 }
834 $crate::cast::__private::GeoArrowType::MultiLineString(_) => {
835 $fn($crate::cast::AsGeoArrowArray::as_multi_line_string($array) $(, $args )*)
836 }
837 $crate::cast::__private::GeoArrowType::MultiPolygon(_) => {
838 $fn($crate::cast::AsGeoArrowArray::as_multi_polygon($array) $(, $args )*)
839 }
840 $crate::cast::__private::GeoArrowType::Geometry(_) => {
841 $fn($crate::cast::AsGeoArrowArray::as_geometry($array) $(, $args )*)
842 }
843 $crate::cast::__private::GeoArrowType::GeometryCollection(_) => $fn(
844 $crate::cast::AsGeoArrowArray::as_geometry_collection($array) $(, $args )*
845 ),
846 $crate::cast::__private::GeoArrowType::Rect(_) => {
847 $fn($crate::cast::AsGeoArrowArray::as_rect($array) $(, $args )*)
848 }
849 $crate::cast::__private::GeoArrowType::Wkb(_) => {
850 $fn($crate::cast::AsGeoArrowArray::as_wkb::<i32>($array) $(, $args )*)
851 }
852 $crate::cast::__private::GeoArrowType::LargeWkb(_) => {
853 $fn($crate::cast::AsGeoArrowArray::as_wkb::<i64>($array) $(, $args )*)
854 }
855 $crate::cast::__private::GeoArrowType::WkbView(_) => {
856 $fn($crate::cast::AsGeoArrowArray::as_wkb_view($array) $(, $args )*)
857 }
858 $crate::cast::__private::GeoArrowType::Wkt(_) => {
859 $fn($crate::cast::AsGeoArrowArray::as_wkt::<i32>($array) $(, $args )*)
860 }
861 $crate::cast::__private::GeoArrowType::LargeWkt(_) => {
862 $fn($crate::cast::AsGeoArrowArray::as_wkt::<i64>($array) $(, $args )*)
863 }
864 $crate::cast::__private::GeoArrowType::WktView(_) => {
865 $fn($crate::cast::AsGeoArrowArray::as_wkt_view($array) $(, $args )*)
866 }
867 }
868 };
869}
870
871#[cfg(test)]
872mod test {
873 use std::sync::Arc;
874
875 use geoarrow_schema::{CoordType, Dimension, WkbType};
876
877 use super::*;
878 use crate::test;
879
880 #[test]
881 fn test_cast_wkb_in_to_wkb() {
882 let wkb_arr: GenericWkbArray<i32> =
883 to_wkb(&test::point::array(CoordType::Separated, Dimension::XY)).unwrap();
884 let wkb_arr2: GenericWkbArray<i32> = to_wkb(&wkb_arr).unwrap();
885 let wkb_arr3: GenericWkbArray<i64> = to_wkb(&wkb_arr2).unwrap();
886 let wkb_arr4: GenericWkbArray<i64> = to_wkb(&wkb_arr3).unwrap();
887 let wkb_arr5: GenericWkbArray<i32> = to_wkb(&wkb_arr4).unwrap();
888 assert_eq!(wkb_arr, wkb_arr5);
889 }
890
891 #[test]
892 fn test_cast_wkt_in_to_wkt() {
893 let wkt_arr: GenericWktArray<i32> =
894 to_wkt(&test::point::array(CoordType::Separated, Dimension::XY)).unwrap();
895 let wkt_arr2: GenericWktArray<i32> = to_wkt(&wkt_arr).unwrap();
896 let wkt_arr3: GenericWktArray<i64> = to_wkt(&wkt_arr2).unwrap();
897 let wkt_arr4: GenericWktArray<i64> = to_wkt(&wkt_arr3).unwrap();
898 let wkt_arr5: GenericWktArray<i32> = to_wkt(&wkt_arr4).unwrap();
899 assert_eq!(wkt_arr, wkt_arr5);
900 }
901
902 #[test]
904 fn test_round_trip_wkb_point() {
905 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
906 for dim in [
907 Dimension::XY,
908 Dimension::XYZ,
909 Dimension::XYM,
910 Dimension::XYZM,
911 ] {
912 let arr = test::point::array(coord_type, dim);
913
914 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
915 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
916 assert_eq!(&arr, arr2.as_point());
917
918 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
919 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
920 assert_eq!(&arr, arr3.as_point());
921 }
922 }
923 }
924
925 #[test]
926 fn test_round_trip_wkb_linestring() {
927 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
928 for dim in [
929 Dimension::XY,
930 Dimension::XYZ,
931 Dimension::XYM,
932 Dimension::XYZM,
933 ] {
934 let arr = test::linestring::array(coord_type, dim);
935
936 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
937 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
938 assert_eq!(&arr, arr2.as_line_string());
939
940 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
941 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
942 assert_eq!(&arr, arr3.as_line_string());
943 }
944 }
945 }
946
947 #[test]
948 fn test_round_trip_wkb_polygon() {
949 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
950 for dim in [
951 Dimension::XY,
952 Dimension::XYZ,
953 Dimension::XYM,
954 Dimension::XYZM,
955 ] {
956 let arr = test::polygon::array(coord_type, dim);
957
958 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
959 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
960 assert_eq!(&arr, arr2.as_polygon());
961
962 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
963 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
964 assert_eq!(&arr, arr3.as_polygon());
965 }
966 }
967 }
968
969 #[test]
970 fn test_round_trip_wkb_multipoint() {
971 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
972 for dim in [
973 Dimension::XY,
974 Dimension::XYZ,
975 Dimension::XYM,
976 Dimension::XYZM,
977 ] {
978 let arr = test::multipoint::array(coord_type, dim);
979
980 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
981 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
982 assert_eq!(&arr, arr2.as_multi_point());
983
984 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
985 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
986 assert_eq!(&arr, arr3.as_multi_point());
987 }
988 }
989 }
990
991 #[test]
992 fn test_round_trip_wkb_multilinestring() {
993 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
994 for dim in [
995 Dimension::XY,
996 Dimension::XYZ,
997 Dimension::XYM,
998 Dimension::XYZM,
999 ] {
1000 let arr = test::multilinestring::array(coord_type, dim);
1001
1002 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
1003 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
1004 assert_eq!(&arr, arr2.as_multi_line_string());
1005
1006 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
1007 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
1008 assert_eq!(&arr, arr3.as_multi_line_string());
1009 }
1010 }
1011 }
1012
1013 #[test]
1014 fn test_round_trip_wkb_multipolygon() {
1015 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1016 for dim in [
1017 Dimension::XY,
1018 Dimension::XYZ,
1019 Dimension::XYM,
1020 Dimension::XYZM,
1021 ] {
1022 let arr = test::multipolygon::array(coord_type, dim);
1023
1024 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
1025 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
1026 assert_eq!(&arr, arr2.as_multi_polygon());
1027
1028 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
1029 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
1030 assert_eq!(&arr, arr3.as_multi_polygon());
1031 }
1032 }
1033 }
1034
1035 #[test]
1036 fn test_round_trip_wkb_geometrycollection() {
1037 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1038 for dim in [
1039 Dimension::XY,
1040 Dimension::XYZ,
1041 Dimension::XYM,
1042 Dimension::XYZM,
1043 ] {
1044 let arr = test::geometrycollection::array(coord_type, dim, false);
1045
1046 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
1047 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
1048 assert_eq!(&arr, arr2.as_geometry_collection());
1049
1050 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
1051 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
1052 assert_eq!(&arr, arr3.as_geometry_collection());
1053 }
1054 }
1055 }
1056
1057 #[test]
1058 fn test_round_trip_wkb_geometry() {
1059 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1060 let arr = test::geometry::array(coord_type, false);
1061
1062 let wkb_arr = to_wkb::<i32>(&arr).unwrap();
1063 let arr2 = from_wkb(&wkb_arr, arr.data_type().clone()).unwrap();
1064 assert_eq!(&arr, arr2.as_geometry());
1065
1066 let wkb_arr2 = to_wkb::<i64>(&arr).unwrap();
1067 let arr3 = from_wkb(&wkb_arr2, arr.data_type().clone()).unwrap();
1068 assert_eq!(&arr, arr3.as_geometry());
1069 }
1070 }
1071
1072 #[test]
1074 fn test_round_trip_wkt_point() {
1075 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1076 for dim in [
1077 Dimension::XY,
1078 Dimension::XYZ,
1079 Dimension::XYM,
1080 Dimension::XYZM,
1081 ] {
1082 let arr = test::point::array(coord_type, dim);
1083
1084 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1085 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1086 assert_eq!(&arr, arr2.as_point());
1087
1088 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1089 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1090 assert_eq!(&arr, arr3.as_point());
1091 }
1092 }
1093 }
1094
1095 #[test]
1096 fn test_round_trip_wkt_linestring() {
1097 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1098 for dim in [
1099 Dimension::XY,
1100 Dimension::XYZ,
1101 Dimension::XYM,
1102 Dimension::XYZM,
1103 ] {
1104 let arr = test::linestring::array(coord_type, dim);
1105
1106 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1107 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1108 assert_eq!(&arr, arr2.as_line_string());
1109
1110 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1111 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1112 assert_eq!(&arr, arr3.as_line_string());
1113 }
1114 }
1115 }
1116
1117 #[test]
1118 fn test_round_trip_wkt_polygon() {
1119 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1120 for dim in [
1121 Dimension::XY,
1122 Dimension::XYZ,
1123 Dimension::XYM,
1124 Dimension::XYZM,
1125 ] {
1126 let arr = test::polygon::array(coord_type, dim);
1127
1128 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1129 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1130 assert_eq!(&arr, arr2.as_polygon());
1131
1132 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1133 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1134 assert_eq!(&arr, arr3.as_polygon());
1135 }
1136 }
1137 }
1138
1139 #[test]
1140 fn test_round_trip_wkt_multipoint() {
1141 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1142 for dim in [
1143 Dimension::XY,
1144 Dimension::XYZ,
1145 Dimension::XYM,
1146 Dimension::XYZM,
1147 ] {
1148 let arr = test::multipoint::array(coord_type, dim);
1149
1150 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1151 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1152 assert_eq!(&arr, arr2.as_multi_point());
1153
1154 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1155 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1156 assert_eq!(&arr, arr3.as_multi_point());
1157 }
1158 }
1159 }
1160
1161 #[test]
1162 fn test_round_trip_wkt_multilinestring() {
1163 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1164 for dim in [
1165 Dimension::XY,
1166 Dimension::XYZ,
1167 Dimension::XYM,
1168 Dimension::XYZM,
1169 ] {
1170 let arr = test::multilinestring::array(coord_type, dim);
1171
1172 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1173 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1174 assert_eq!(&arr, arr2.as_multi_line_string());
1175
1176 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1177 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1178 assert_eq!(&arr, arr3.as_multi_line_string());
1179 }
1180 }
1181 }
1182
1183 #[test]
1184 fn test_round_trip_wkt_multipolygon() {
1185 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1186 for dim in [
1187 Dimension::XY,
1188 Dimension::XYZ,
1189 Dimension::XYM,
1190 Dimension::XYZM,
1191 ] {
1192 let arr = test::multipolygon::array(coord_type, dim);
1193
1194 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1195 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1196 assert_eq!(&arr, arr2.as_multi_polygon());
1197
1198 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1199 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1200 assert_eq!(&arr, arr3.as_multi_polygon());
1201 }
1202 }
1203 }
1204
1205 #[test]
1206 fn test_round_trip_wkt_geometrycollection() {
1207 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1208 for dim in [
1209 Dimension::XY,
1210 Dimension::XYZ,
1211 Dimension::XYM,
1212 Dimension::XYZM,
1213 ] {
1214 let arr = test::geometrycollection::array(coord_type, dim, false);
1215
1216 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1217 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1218 assert_eq!(&arr, arr2.as_geometry_collection());
1219
1220 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1221 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1222 assert_eq!(&arr, arr3.as_geometry_collection());
1223 }
1224 }
1225 }
1226
1227 #[test]
1228 fn test_round_trip_wkt_geometry() {
1229 for coord_type in [CoordType::Interleaved, CoordType::Separated] {
1230 let arr = test::geometry::array(coord_type, false);
1231
1232 let wkt_arr = to_wkt::<i32>(&arr).unwrap();
1233 let arr2 = from_wkt(&wkt_arr, arr.data_type().clone()).unwrap();
1234 assert_eq!(&arr, arr2.as_geometry());
1235
1236 let wkt_arr2 = to_wkt::<i64>(&arr).unwrap();
1237 let arr3 = from_wkt(&wkt_arr2, arr.data_type().clone()).unwrap();
1238 assert_eq!(&arr, arr3.as_geometry());
1239 }
1240 }
1241
1242 #[allow(dead_code)]
1244 fn _to_wkb_test_downcast_macro(
1245 arr: &dyn GeoArrowArray,
1246 ) -> GeoArrowResult<GenericWkbArray<i32>> {
1247 downcast_geoarrow_array!(arr, impl_to_wkb)
1248 }
1249
1250 fn impl_to_wkb<'a>(
1251 geo_arr: &'a impl GeoArrowArrayAccessor<'a>,
1252 ) -> GeoArrowResult<GenericWkbArray<i32>> {
1253 let geoms = geo_arr
1254 .iter()
1255 .map(|x| x.transpose())
1256 .collect::<std::result::Result<Vec<_>, _>>()
1257 .unwrap();
1258 let wkb_type = WkbType::new(geo_arr.data_type().metadata().clone());
1259 Ok(WkbBuilder::from_nullable_geometries(geoms.as_slice(), wkb_type)?.finish())
1260 }
1261
1262 #[test]
1264 fn test_downcast_macro_with_param() {
1265 let arr =
1266 Arc::new(test::geometry::array(Default::default(), false)) as Arc<dyn GeoArrowArray>;
1267 let arr_ref = arr.as_ref();
1268 let x = downcast_geoarrow_array!(arr_ref, impl_inner_function_with_param, 1.0).unwrap();
1269 assert_eq!(x, 1.0);
1270 }
1271
1272 fn impl_inner_function_with_param<'a>(
1273 _geo_arr: &'a impl GeoArrowArrayAccessor<'a>,
1274 param: f64,
1275 ) -> GeoArrowResult<f64> {
1276 Ok(param)
1277 }
1278}