(
text_array: V,
pair_delim_array: Option<V>,
kv_delim_array: Option<V>,
)
| 178 | } |
| 179 | |
| 180 | fn str_to_map_impl<'a, V: StringArrayType<'a> + Copy>( |
| 181 | text_array: V, |
| 182 | pair_delim_array: Option<V>, |
| 183 | kv_delim_array: Option<V>, |
| 184 | ) -> Result<ArrayRef> { |
| 185 | let num_rows = text_array.len(); |
| 186 | |
| 187 | // Precompute combined null buffer from all input arrays. |
| 188 | // NullBuffer::union_many performs a bitmap-level AND, which is more |
| 189 | // efficient than checking per-row nullability inline. |
| 190 | let combined_nulls = NullBuffer::union_many([ |
| 191 | text_array.nulls(), |
| 192 | pair_delim_array.as_ref().and_then(|a| a.nulls()), |
| 193 | kv_delim_array.as_ref().and_then(|a| a.nulls()), |
| 194 | ]); |
| 195 | |
| 196 | // Use field names matching map_type_from_key_value_types: "key" and "value" |
| 197 | let field_names = MapFieldNames { |
| 198 | entry: "entries".to_string(), |
| 199 | key: "key".to_string(), |
| 200 | value: "value".to_string(), |
| 201 | }; |
| 202 | let mut map_builder = MapBuilder::new( |
| 203 | Some(field_names), |
| 204 | StringBuilder::new(), |
| 205 | StringBuilder::new(), |
| 206 | ); |
| 207 | |
| 208 | let mut seen_keys = HashSet::new(); |
| 209 | for row_idx in 0..num_rows { |
| 210 | if combined_nulls.as_ref().is_some_and(|n| n.is_null(row_idx)) { |
| 211 | map_builder.append(false)?; |
| 212 | continue; |
| 213 | } |
| 214 | |
| 215 | // Per-row delimiter extraction |
| 216 | let pair_delim = |
| 217 | pair_delim_array.map_or(DEFAULT_PAIR_DELIM, |a| a.value(row_idx)); |
| 218 | let kv_delim = kv_delim_array.map_or(DEFAULT_KV_DELIM, |a| a.value(row_idx)); |
| 219 | |
| 220 | let text = text_array.value(row_idx); |
| 221 | if text.is_empty() { |
| 222 | // Empty string -> map with empty key and NULL value (Spark behavior) |
| 223 | map_builder.keys().append_value(""); |
| 224 | map_builder.values().append_null(); |
| 225 | map_builder.append(true)?; |
| 226 | continue; |
| 227 | } |
| 228 | |
| 229 | seen_keys.clear(); |
| 230 | for pair in text.split(pair_delim) { |
| 231 | if pair.is_empty() { |
| 232 | continue; |
| 233 | } |
| 234 | |
| 235 | let mut kv_iter = pair.splitn(2, kv_delim); |
| 236 | let key = kv_iter.next().unwrap_or(""); |
| 237 | let value = kv_iter.next(); |
no test coverage detected
searching dependent graphs…