1use std::sync::Arc;
2
3use arrow_array::cast::AsArray;
4use arrow_array::{
5 Array, ArrayRef, ArrowPrimitiveType, BooleanArray, Int64Array, PrimitiveArray, UInt64Array,
6 new_empty_array,
7};
8use arrow_cast::cast;
9use arrow_schema::{ArrowError, DataType};
10use arrow_select::concat::concat;
11use arrow_select::filter::filter;
12use arrow_select::take::take;
13use runlength::{Keep, Plan, Rle, RleLike, merge_plan, plan};
14
15use crate::batch::ArrowRleBatch;
16use crate::error::{Error, Result};
17use crate::identical::identical_neighbours;
18use crate::kernels::Kernel;
19
20#[derive(Clone, Debug)]
26pub struct ArrowRle {
27 pub(crate) ends: Vec<i64>,
28 pub(crate) values: ArrayRef,
29}
30
31fn validate_ends(ends: &[i64]) -> Result<()> {
32 let mut prev = 0;
33 for (index, &end) in ends.iter().enumerate() {
34 if end <= prev {
35 return Err(runlength::Error::InvalidEnds { index }.into());
36 }
37 prev = end;
38 }
39 Ok(())
40}
41
42fn check_same_len(what: &'static str, left: usize, right: usize) -> Result<()> {
43 if left != right {
44 return Err(runlength::Error::LengthMismatch { what, left, right }.into());
45 }
46 Ok(())
47}
48
49pub fn default_fill(data_type: &DataType) -> Option<ArrayRef> {
52 if data_type == &DataType::Boolean {
53 return Some(Arc::new(BooleanArray::from(vec![false])));
54 }
55 if data_type.is_numeric() {
56 return cast(&Int64Array::from(vec![0]), data_type).ok();
57 }
58 None
59}
60
61pub(crate) fn gather(
63 values: &ArrayRef,
64 idx: &[usize],
65 fill: Option<&dyn Array>,
66) -> Result<ArrayRef> {
67 let n = values.len();
68 if idx.len() == n && idx.iter().enumerate().all(|(k, &i)| k == i) {
69 return Ok(values.clone());
70 }
71 let source = if idx.last() == Some(&n) {
73 let fill = fill.expect("the length check guarantees a fill value past the end");
74 concat(&[values.as_ref(), fill])?
75 } else {
76 values.clone()
77 };
78 let indices = UInt64Array::from_iter_values(idx.iter().map(|&i| i as u64));
79 Ok(take(source.as_ref(), &indices, None)?)
80}
81
82pub(crate) fn array_ref(array: &dyn Array) -> ArrayRef {
84 arrow_array::make_array(array.to_data())
85}
86
87pub(crate) fn check_fill(fill: Option<&dyn Array>, data_type: &DataType) -> Result<()> {
88 if let Some(fill) = fill {
89 if fill.len() != 1 || fill.data_type() != data_type {
90 return Err(Error::InvalidFill {
91 expected: data_type.clone(),
92 actual: fill.data_type().clone(),
93 len: fill.len(),
94 });
95 }
96 }
97 Ok(())
98}
99
100impl ArrowRle {
101 pub fn try_new(ends: Vec<i64>, values: ArrayRef) -> Result<Self> {
103 check_same_len("ends and values", ends.len(), values.len())?;
104 validate_ends(&ends)?;
105 Ok(ArrowRle { ends, values })
106 }
107
108 pub fn from_runs(runs: &[i64], values: ArrayRef) -> Result<Self> {
111 check_same_len("runs and values", runs.len(), values.len())?;
112 let mut ends = Vec::with_capacity(runs.len());
113 let mut total: i64 = 0;
114 for (index, &run) in runs.iter().enumerate() {
115 if run < 0 {
116 return Err(runlength::Error::NegativeRun { index, run }.into());
117 }
118 if run > 0 {
119 total = total.checked_add(run).ok_or(runlength::Error::Overflow)?;
120 ends.push(total);
121 }
122 }
123 let values = if ends.len() < runs.len() {
124 let keep = BooleanArray::from_iter(runs.iter().map(|&r| Some(r > 0)));
125 filter(values.as_ref(), &keep)?
126 } else {
127 values
128 };
129 Ok(ArrowRle { ends, values })
130 }
131
132 pub fn from_dense(values: ArrayRef) -> Result<Self> {
134 let ends = (1..=values.len() as i64).collect();
135 ArrowRle { ends, values }.merge()
136 }
137
138 pub fn empty(data_type: &DataType) -> Self {
140 ArrowRle {
141 ends: Vec::new(),
142 values: new_empty_array(data_type),
143 }
144 }
145
146 pub fn from_rle<T: ArrowPrimitiveType>(rle: &Rle<T::Native>) -> Self {
148 ArrowRle {
149 ends: rle.ends().to_vec(),
150 values: Arc::new(PrimitiveArray::<T>::from_iter_values(
151 rle.values().iter().copied(),
152 )),
153 }
154 }
155
156 pub fn to_rle<T: ArrowPrimitiveType>(&self) -> Result<Rle<T::Native>> {
159 let values = self
160 .values
161 .as_primitive_opt::<T>()
162 .ok_or_else(|| Error::UnsupportedType(self.values.data_type().clone()))?;
163 if values.null_count() > 0 {
164 return Err(Error::UnexpectedNulls);
165 }
166 Ok(Rle::from_ends(self.ends.clone(), values.values().to_vec())?)
167 }
168
169 pub fn ends(&self) -> &[i64] {
171 &self.ends
172 }
173
174 pub fn values(&self) -> &ArrayRef {
176 &self.values
177 }
178
179 pub fn data_type(&self) -> &DataType {
180 self.values.data_type()
181 }
182
183 pub fn len(&self) -> i64 {
185 self.ends.last().copied().unwrap_or(0)
186 }
187
188 pub fn is_empty(&self) -> bool {
189 self.ends.is_empty()
190 }
191
192 pub fn num_runs(&self) -> usize {
193 self.ends.len()
194 }
195
196 pub fn runs(&self) -> Vec<i64> {
198 let mut prev = 0;
199 self.ends
200 .iter()
201 .map(|&end| {
202 let run = end - prev;
203 prev = end;
204 run
205 })
206 .collect()
207 }
208
209 pub fn into_parts(self) -> (Vec<i64>, ArrayRef) {
210 (self.ends, self.values)
211 }
212
213 pub fn run_index(&self, pos: i64) -> Option<usize> {
215 (0..self.len())
216 .contains(&pos)
217 .then(|| self.ends.partition_point(|&end| end <= pos))
218 }
219
220 pub fn slice(&self, start: i64, end: i64) -> ArrowRle {
223 let (start, end) = (start.max(0), end.min(self.len()));
224 if start >= end {
225 return ArrowRle::empty(self.data_type());
226 }
227 let first = self.ends.partition_point(|&e| e <= start);
228 let last = self.ends.partition_point(|&e| e < end);
229 let mut ends: Vec<i64> = self.ends[first..last].iter().map(|&e| e - start).collect();
230 ends.push(end - start);
231 ArrowRle {
232 ends,
233 values: self.values.slice(first, last - first + 1),
234 }
235 }
236
237 pub fn getitems(&self, starts: &[i64], ends: &[i64]) -> Result<ArrowRleBatch> {
240 check_same_len("starts and ends", starts.len(), ends.len())?;
241 let mut offsets = Vec::with_capacity(starts.len() + 1);
242 offsets.push(0);
243 let mut out_ends = Vec::new();
244 let mut run_ids = Vec::new();
245 for (index, (&start, &end)) in starts.iter().zip(ends).enumerate() {
246 if start < 0 || end < start {
247 return Err(runlength::Error::InvalidInterval { index, start, end }.into());
248 }
249 let (start, end) = (start, end.min(self.len()));
250 if start < end {
251 let first = self.ends.partition_point(|&e| e <= start);
252 let last = self.ends.partition_point(|&e| e < end);
253 out_ends.extend(self.ends[first..last].iter().map(|&e| e - start));
254 out_ends.push(end - start);
255 run_ids.extend(first as u64..=last as u64);
256 }
257 offsets.push(out_ends.len());
258 }
259 let values = take(self.values.as_ref(), &UInt64Array::from(run_ids), None)?;
260 let keys = UInt64Array::from_iter_values(0..starts.len() as u64);
261 ArrowRleBatch::from_parts_unchecked(
262 crate::batch::single_key_column("slice", Arc::new(keys)),
263 offsets,
264 out_ends,
265 values,
266 )
267 }
268
269 pub fn to_dense(&self) -> Result<ArrayRef> {
271 let mut indices = Vec::with_capacity(self.len() as usize);
272 for (i, run) in self.runs().into_iter().enumerate() {
273 indices.extend(std::iter::repeat_n(i as u64, run as usize));
274 }
275 Ok(take(
276 self.values.as_ref(),
277 &UInt64Array::from(indices),
278 None,
279 )?)
280 }
281
282 pub fn plan_with(&self, other: &ArrowRle) -> Plan {
284 plan(&self.ends, &other.ends)
285 }
286
287 pub fn identical_neighbours(&self) -> Result<Vec<bool>> {
289 identical_neighbours(self.values.as_ref())
290 }
291
292 pub fn is_merged(&self) -> Result<bool> {
294 Ok(!self.identical_neighbours()?.into_iter().any(|x| x))
295 }
296
297 pub fn merge(self) -> Result<Self> {
299 let mask = self.identical_neighbours()?;
300 self.merge_mask(&mask, Keep::First)
301 }
302
303 pub fn merge_mask(self, mask: &[bool], keep: Keep) -> Result<Self> {
306 let groups = merge_plan(&self.ends, mask)?;
307 if groups.num_groups() == self.ends.len() {
308 return Ok(self);
309 }
310 let kept = groups.offsets.windows(2).map(|w| match keep {
311 Keep::First => w[0] as u64,
312 Keep::Last => w[1] as u64 - 1,
313 });
314 let values = take(
315 self.values.as_ref(),
316 &UInt64Array::from_iter_values(kept),
317 None,
318 )?;
319 Ok(ArrowRle {
320 ends: groups.ends,
321 values,
322 })
323 }
324
325 pub fn zip_with<F>(
333 &self,
334 other: &ArrowRle,
335 fill_a: Option<&dyn Array>,
336 fill_b: Option<&dyn Array>,
337 f: F,
338 ) -> Result<ArrowRle>
339 where
340 F: FnOnce(&dyn Array, &dyn Array) -> std::result::Result<ArrayRef, ArrowError>,
341 {
342 self.zip_with_raw(other, fill_a, fill_b, f)?.merge()
343 }
344
345 pub fn zip_with_raw<F>(
347 &self,
348 other: &ArrowRle,
349 fill_a: Option<&dyn Array>,
350 fill_b: Option<&dyn Array>,
351 f: F,
352 ) -> Result<ArrowRle>
353 where
354 F: FnOnce(&dyn Array, &dyn Array) -> std::result::Result<ArrayRef, ArrowError>,
355 {
356 check_fill(fill_a, self.data_type())?;
357 check_fill(fill_b, other.data_type())?;
358 let (len_a, len_b) = (self.len(), other.len());
359 if (len_a < len_b && fill_a.is_none()) || (len_b < len_a && fill_b.is_none()) {
360 return Err(runlength::Error::UnequalLength {
361 left: len_a,
362 right: len_b,
363 }
364 .into());
365 }
366 let p = self.plan_with(other);
367 let a = gather(&self.values, &p.idx_a, fill_a)?;
368 let b = gather(&other.values, &p.idx_b, fill_b)?;
369 let values = f(a.as_ref(), b.as_ref())?;
370 if values.len() != p.ends.len() {
371 return Err(Error::WrongLength {
372 expected: p.ends.len(),
373 actual: values.len(),
374 });
375 }
376 Ok(ArrowRle {
377 ends: p.ends,
378 values,
379 })
380 }
381
382 pub fn map<F>(&self, f: F) -> Result<ArrowRle>
384 where
385 F: FnOnce(&dyn Array) -> std::result::Result<ArrayRef, ArrowError>,
386 {
387 let values = f(self.values.as_ref())?;
388 if values.len() != self.values.len() {
389 return Err(Error::WrongLength {
390 expected: self.values.len(),
391 actual: values.len(),
392 });
393 }
394 ArrowRle {
395 ends: self.ends.clone(),
396 values,
397 }
398 .merge()
399 }
400
401 pub fn cast(&self, data_type: &DataType) -> Result<ArrowRle> {
404 if self.data_type() == data_type {
405 return Ok(self.clone());
406 }
407 let values = cast(self.values.as_ref(), data_type)?;
408 ArrowRle {
409 ends: self.ends.clone(),
410 values,
411 }
412 .merge()
413 }
414
415 pub fn zip_with_default(&self, other: &ArrowRle, f: Kernel) -> Result<ArrowRle> {
417 self.op(other, f)
418 }
419
420 fn op(&self, other: &ArrowRle, f: Kernel) -> Result<ArrowRle> {
421 let fill_a = default_fill(self.data_type());
422 let fill_b = default_fill(other.data_type());
423 self.zip_with(other, fill_a.as_deref(), fill_b.as_deref(), f)
424 }
425}
426
427crate::kernels::kernel_methods!(
428 ArrowRle,
429 " The shorter side is padded with [`default_fill`]."
430);
431
432impl PartialEq for ArrowRle {
433 fn eq(&self, other: &Self) -> bool {
436 if self.len() != other.len() || self.data_type() != other.data_type() {
437 return false;
438 }
439 let p = self.plan_with(other);
440 let (Ok(a), Ok(b)) = (
441 gather(&self.values, &p.idx_a, None),
442 gather(&other.values, &p.idx_b, None),
443 ) else {
444 return false;
445 };
446 let n = a.len();
448 let indices: Vec<(usize, usize)> = (0..n).flat_map(|k| [(0, k), (1, k)]).collect();
449 let Ok(pairs) = arrow_select::interleave::interleave(&[a.as_ref(), b.as_ref()], &indices)
450 else {
451 return false;
452 };
453 identical_neighbours(pairs.as_ref())
454 .map(|mask| mask.into_iter().step_by(2).all(|x| x))
455 .unwrap_or(false)
456 }
457}