1use std::{str::FromStr, sync::Arc};
18
19use arrow_array::{ArrayRef, BinaryArray, BinaryViewArray};
20use datafusion_common::ScalarValue;
21use datafusion_expr::ColumnarValue;
22use sedona_schema::datatypes::SedonaType;
23use wkb::{writer::WriteOptions, Endianness};
24use wkt::Wkt;
25
26pub fn create_array_value(wkt_values: &[Option<&str>], data_type: &SedonaType) -> ColumnarValue {
30 ColumnarValue::Array(create_array_storage(wkt_values, data_type))
31}
32
33pub fn create_scalar_value(wkt_value: Option<&str>, data_type: &SedonaType) -> ColumnarValue {
37 ColumnarValue::Scalar(create_scalar_storage(wkt_value, data_type))
38}
39
40pub fn create_scalar(wkt_value: Option<&str>, data_type: &SedonaType) -> ScalarValue {
44 create_scalar_storage(wkt_value, data_type)
45}
46
47pub fn create_array(wkt_values: &[Option<&str>], data_type: &SedonaType) -> ArrayRef {
51 create_array_storage(wkt_values, data_type)
52}
53
54pub fn create_array_storage(wkt_values: &[Option<&str>], data_type: &SedonaType) -> ArrayRef {
58 match data_type {
59 SedonaType::Wkb(_, _) => Arc::new(make_wkb_array::<BinaryArray>(wkt_values)),
60 SedonaType::WkbView(_, _) => Arc::new(make_wkb_array::<BinaryViewArray>(wkt_values)),
61 _ => panic!("create_array_storage not implemented for {data_type:?}"),
62 }
63}
64
65pub fn create_scalar_storage(wkt_value: Option<&str>, data_type: &SedonaType) -> ScalarValue {
69 match data_type {
70 SedonaType::Wkb(_, _) => ScalarValue::Binary(wkt_value.map(make_wkb)),
71 SedonaType::WkbView(_, _) => ScalarValue::BinaryView(wkt_value.map(make_wkb)),
72 _ => panic!("create_scalar_storage not implemented for {data_type:?}"),
73 }
74}
75
76fn make_wkb_array<T>(wkt_values: &[Option<&str>]) -> T
77where
78 T: FromIterator<Option<Vec<u8>>>,
79{
80 wkt_values
81 .iter()
82 .map(|maybe_wkt| maybe_wkt.map(make_wkb))
83 .collect()
84}
85
86pub fn make_wkb(wkt_value: &str) -> Vec<u8> {
88 let geom = Wkt::<f64>::from_str(wkt_value).unwrap();
89 let mut out: Vec<u8> = vec![];
90 wkb::writer::write_geometry(
91 &mut out,
92 &geom,
93 &WriteOptions {
94 endianness: Endianness::LittleEndian,
95 },
96 )
97 .unwrap();
98 out
99}
100
101#[cfg(test)]
102mod tests {
103 use arrow_schema::DataType;
104 use datafusion_common::cast::as_binary_array;
105 use sedona_schema::datatypes::{WKB_GEOMETRY, WKB_VIEW_GEOMETRY};
106
107 use super::*;
108
109 #[test]
110 fn scalars() {
111 let wkb_scalar = create_scalar_storage(Some("POINT (0 1)"), &WKB_GEOMETRY);
112 assert_eq!(&wkb_scalar.data_type(), WKB_GEOMETRY.storage_type());
113 assert!(create_scalar_storage(None, &WKB_GEOMETRY).is_null());
114
115 let wkb_view_scalar = create_scalar_storage(Some("POINT (0 1)"), &WKB_VIEW_GEOMETRY);
116 assert_eq!(
117 &wkb_view_scalar.data_type(),
118 WKB_VIEW_GEOMETRY.storage_type()
119 );
120 assert!(create_scalar_storage(None, &WKB_VIEW_GEOMETRY).is_null());
121 }
122
123 #[test]
124 #[should_panic(expected = "create_scalar_storage not implemented")]
125 fn scalar_storage_invalid() {
126 create_scalar_storage(Some("POINT (0 1)"), &SedonaType::Arrow(DataType::Null));
127 }
128
129 #[test]
130 fn arrays() {
131 let wkb_array = create_array_storage(
132 &[Some("POINT (0 1)"), None, Some("POINT (1 2)")],
133 &WKB_GEOMETRY,
134 );
135 assert_eq!(wkb_array.data_type(), WKB_GEOMETRY.storage_type());
136 assert_eq!(wkb_array.len(), 3);
137 let wkb_binary_array = as_binary_array(&wkb_array).unwrap();
138 assert_eq!(
139 wkb_binary_array
140 .iter()
141 .map(|maybe_item| maybe_item.is_some())
142 .collect::<Vec<bool>>(),
143 vec![true, false, true]
144 );
145
146 let wkb_array = create_array_storage(
147 &[Some("POINT (0 1)"), None, Some("POINT (1 2)")],
148 &WKB_VIEW_GEOMETRY,
149 );
150 assert_eq!(wkb_array.data_type(), WKB_VIEW_GEOMETRY.storage_type());
151 }
152
153 #[test]
154 #[should_panic(expected = "create_array_storage not implemented")]
155 fn array_storage_invalid() {
156 create_array_storage(&[Some("POINT (0 1)")], &SedonaType::Arrow(DataType::Null));
157 }
158}