1use std::marker::PhantomData;
4use std::ops::Range;
5use std::sync::Arc;
6
7use arrow_array::{ArrayRef, ArrowPrimitiveType, PrimitiveArray};
8use arrow_buffer::ScalarBuffer;
9use sample_std::{
10 arbitrary, sampler_choice, valid_f32, valid_f64, Random, Sample, Shrunk, VecSampler,
11};
12
13use crate::{ArrowLenSampler, ArrowSampler, Bitmap, SampleLen, SetLen};
14
15#[derive(Debug, Clone)]
16pub struct PrimitiveArraySampler<PT, V, T> {
17 len: usize,
18 inner: PT,
19 validity: V,
20 _phantom: PhantomData<T>,
21}
22
23impl<PT, V, T> SetLen for PrimitiveArraySampler<PT, V, T>
24where
25 V: SetLen,
26{
27 fn set_len(&mut self, len: usize) {
28 self.len = len;
29 self.validity.set_len(len);
30 }
31}
32
33impl<PT, V, T> SampleLen for PrimitiveArraySampler<PT, V, T>
34where
35 PT: Sample + 'static,
36 T: ArrowPrimitiveType + 'static,
37 T::Native: From<PT::Output>,
38 V: Sample<Output = Option<Bitmap>> + SetLen + 'static,
39{
40}
41
42impl<PT, V, T> Sample for PrimitiveArraySampler<PT, V, T>
43where
44 PT: Sample,
45 T: ArrowPrimitiveType,
46 T::Native: From<PT::Output>,
47 V: Sample<Output = Option<Bitmap>> + SetLen,
48{
49 type Output = ArrayRef;
50
51 fn generate(&mut self, g: &mut Random) -> Self::Output {
52 let values: Vec<T::Native> = (0..self.len)
54 .map(|_| T::Native::from(self.inner.generate(g)))
55 .collect();
56
57 let values_buffer = ScalarBuffer::from(values);
59
60 let null_buffer = self.validity.generate(g).map(|bitmap| bitmap);
62
63 Arc::new(PrimitiveArray::<T>::new(values_buffer, null_buffer))
65 }
66
67 fn shrink(&self, _: Self::Output) -> Shrunk<Self::Output> {
68 Box::new(std::iter::empty())
69 }
70}
71
72pub fn primitive_len_sampler<PT, V, T>(inner: PT, validity: V) -> ArrowLenSampler
73where
74 PT: Sample + 'static,
75 T: ArrowPrimitiveType + 'static,
76 T::Native: From<PT::Output>,
77 V: Sample<Output = Option<Bitmap>> + SetLen + 'static,
78{
79 Box::new(PrimitiveArraySampler::<PT, V, T> {
80 len: 0,
81 inner,
82 validity,
83 _phantom: PhantomData,
84 })
85}
86
87macro_rules! primitive_samplers {
89 ($type:ty, $arrow_type:ty, $fn_name:ident) => {
90 pub fn $fn_name(
91 validity: impl Sample<Output = Option<Bitmap>> + SetLen + Clone + 'static,
92 ) -> ArrowLenSampler {
93 primitive_len_sampler::<_, _, $arrow_type>(arbitrary::<$type>(), validity)
94 }
95 };
96}
97
98primitive_samplers!(i8, arrow_array::types::Int8Type, i8_sampler);
100primitive_samplers!(i16, arrow_array::types::Int16Type, i16_sampler);
101primitive_samplers!(i32, arrow_array::types::Int32Type, i32_sampler);
102primitive_samplers!(i64, arrow_array::types::Int64Type, i64_sampler);
103primitive_samplers!(u8, arrow_array::types::UInt8Type, u8_sampler);
104primitive_samplers!(u16, arrow_array::types::UInt16Type, u16_sampler);
105primitive_samplers!(u32, arrow_array::types::UInt32Type, u32_sampler);
106primitive_samplers!(u64, arrow_array::types::UInt64Type, u64_sampler);
107primitive_samplers!(f32, arrow_array::types::Float32Type, f32_sampler);
108primitive_samplers!(f64, arrow_array::types::Float64Type, f64_sampler);
109
110pub fn valid_float_len_sampler<V>(valid: V) -> ArrowLenSampler
111where
112 V: Sample<Output = Option<Bitmap>> + SetLen + Clone + 'static,
113{
114 Box::new(sampler_choice([
115 primitive_len_sampler::<_, _, arrow_array::types::Float32Type>(valid_f32(), valid.clone()),
116 primitive_len_sampler::<_, _, arrow_array::types::Float64Type>(valid_f64(), valid),
117 ]))
118}
119
120pub fn arbitrary_int_len_sampler<V>(valid: V) -> ArrowLenSampler
121where
122 V: Sample<Output = Option<Bitmap>> + SetLen + Clone + 'static,
123{
124 Box::new(sampler_choice([
125 i8_sampler(valid.clone()),
126 i16_sampler(valid.clone()),
127 i32_sampler(valid.clone()),
128 i64_sampler(valid.clone()),
129 ]))
130}
131
132pub fn arbitrary_uint_len_sampler<V>(valid: V) -> ArrowLenSampler
133where
134 V: Sample<Output = Option<Bitmap>> + SetLen + Clone + 'static,
135{
136 Box::new(sampler_choice([
137 u8_sampler(valid.clone()),
138 u16_sampler(valid.clone()),
139 u32_sampler(valid.clone()),
140 u64_sampler(valid.clone()),
141 ]))
142}
143
144pub fn valid_primitive_len<V>(valid: V) -> ArrowLenSampler
145where
146 V: Sample<Output = Option<Bitmap>> + SetLen + Clone + 'static,
147{
148 Box::new(sampler_choice([
149 valid_float_len_sampler(valid.clone()),
150 arbitrary_int_len_sampler(valid.clone()),
151 arbitrary_uint_len_sampler(valid.clone()),
152 ]))
153}
154
155pub fn arbitrary_primitive_len<V>(valid: V) -> ArrowLenSampler
156where
157 V: Sample<Output = Option<Bitmap>> + SetLen + Clone + 'static,
158{
159 valid_primitive_len(valid)
160}
161
162#[derive(Debug, Clone)]
163pub struct ProtoNullablePrimitiveArray<PT, T> {
164 inner: VecSampler<Range<usize>, PT>,
165 _phantom: PhantomData<T>,
166}
167
168impl<PT, N, T> Sample for ProtoNullablePrimitiveArray<PT, T>
169where
170 PT: Sample<Output = Option<N>> + Clone + 'static,
171 N: Clone + 'static,
172 T: ArrowPrimitiveType + 'static,
173 T::Native: From<N>,
174{
175 type Output = ArrayRef;
176
177 fn generate(&mut self, g: &mut Random) -> Self::Output {
178 let values: Vec<Option<T::Native>> = self
180 .inner
181 .generate(g)
182 .into_iter()
183 .map(|opt| opt.map(T::Native::from))
184 .collect();
185
186 Arc::new(PrimitiveArray::<T>::from_iter(values))
188 }
189
190 fn shrink(&self, _: Self::Output) -> Shrunk<Self::Output> {
191 Box::new(std::iter::empty())
192 }
193}
194
195#[derive(Debug, Clone)]
196pub struct ProtoPrimitiveArray<PT, T> {
197 inner: VecSampler<Range<usize>, PT>,
198 _phantom: PhantomData<T>,
199}
200
201impl<PT, N, T> Sample for ProtoPrimitiveArray<PT, T>
202where
203 PT: Sample<Output = N> + Clone + 'static,
204 N: Clone + 'static,
205 T: ArrowPrimitiveType + 'static,
206 T::Native: From<N>,
207{
208 type Output = ArrayRef;
209
210 fn generate(&mut self, g: &mut Random) -> Self::Output {
211 let values: Vec<T::Native> = self
213 .inner
214 .generate(g)
215 .into_iter()
216 .map(T::Native::from)
217 .collect();
218
219 let buffer = ScalarBuffer::from(values);
221
222 Arc::new(PrimitiveArray::<T>::new(buffer, None))
224 }
225
226 fn shrink(&self, _: Self::Output) -> Shrunk<Self::Output> {
227 Box::new(std::iter::empty())
228 }
229}
230
231#[derive(Clone)]
232pub struct ProtoBoxedNullablePrimitiveArray<PT, T> {
233 inner: ProtoNullablePrimitiveArray<PT, T>,
234}
235
236impl<PT, N, T> Sample for ProtoBoxedNullablePrimitiveArray<PT, T>
237where
238 PT: Sample<Output = Option<N>> + Clone + 'static,
239 N: Clone + 'static,
240 T: ArrowPrimitiveType + 'static,
241 T::Native: From<N>,
242{
243 type Output = ArrayRef;
244
245 fn generate(&mut self, g: &mut Random) -> Self::Output {
246 self.inner.generate(g)
247 }
248
249 fn shrink(&self, _: Self::Output) -> Shrunk<Self::Output> {
250 Box::new(std::iter::empty())
251 }
252}
253
254pub fn boxed_nullable<GT, N, T>(len: Range<usize>, el: GT) -> ArrowSampler
255where
256 GT: Sample<Output = Option<N>> + Send + Sync + Clone + 'static,
257 N: Clone + Send + Sync + 'static,
258 T: ArrowPrimitiveType + Send + Sync + 'static,
259 T::Native: From<N>,
260{
261 Box::new(ProtoBoxedNullablePrimitiveArray {
262 inner: ProtoNullablePrimitiveArray {
263 inner: VecSampler { length: len, el },
264 _phantom: PhantomData::<T>,
265 },
266 })
267}
268
269pub fn boxed<GT, N, T>(len: Range<usize>, el: GT) -> ArrowSampler
270where
271 GT: Sample<Output = N> + Send + Sync + Clone + 'static,
272 N: Clone + Send + Sync + 'static,
273 T: ArrowPrimitiveType + Send + Sync + 'static,
274 T::Native: From<N>,
275{
276 Box::new(ProtoPrimitiveArray {
277 inner: VecSampler { length: len, el },
278 _phantom: PhantomData::<T>,
279 })
280}
281
282#[derive(Clone)]
283struct Nullable<SI, V> {
284 inner: SI,
285 null: V,
286}
287
288impl<SI, V> Sample for Nullable<SI, V>
289where
290 SI: Sample,
291 V: Sample<Output = bool>,
292{
293 type Output = Option<SI::Output>;
294 fn generate(&mut self, g: &mut Random) -> Self::Output {
295 if self.null.generate(g) {
296 None
297 } else {
298 Some(self.inner.generate(g))
299 }
300 }
301
302 fn shrink(&self, v: Self::Output) -> Shrunk<Self::Output> {
303 if let Some(v) = v {
304 Box::new(std::iter::once(None).chain(self.inner.shrink(v).map(Some)))
305 } else {
306 Box::new(std::iter::empty())
307 }
308 }
309}
310
311macro_rules! boxed_primitives {
313 ($type:ty, $arrow_type:ty, $fn_name:ident) => {
314 pub fn $fn_name<V>(len: Range<usize>, null: Option<V>) -> ArrowSampler
315 where
316 V: Sample<Output = bool> + Clone + Send + Sync + 'static,
317 {
318 match null {
319 Some(null) => boxed_nullable::<_, $type, $arrow_type>(
320 len.clone(),
321 Nullable {
322 inner: arbitrary::<$type>(),
323 null,
324 },
325 ),
326 None => boxed::<_, $type, $arrow_type>(len.clone(), arbitrary::<$type>()),
327 }
328 }
329 };
330}
331
332boxed_primitives!(i8, arrow_array::types::Int8Type, i8_array);
334boxed_primitives!(i16, arrow_array::types::Int16Type, i16_array);
335boxed_primitives!(i32, arrow_array::types::Int32Type, i32_array);
336boxed_primitives!(i64, arrow_array::types::Int64Type, i64_array);
337boxed_primitives!(u8, arrow_array::types::UInt8Type, u8_array);
338boxed_primitives!(u16, arrow_array::types::UInt16Type, u16_array);
339boxed_primitives!(u32, arrow_array::types::UInt32Type, u32_array);
340boxed_primitives!(u64, arrow_array::types::UInt64Type, u64_array);
341boxed_primitives!(f32, arrow_array::types::Float32Type, f32_array);
342boxed_primitives!(f64, arrow_array::types::Float64Type, f64_array);
343
344pub fn valid_float_array<V>(len: Range<usize>, null: Option<V>) -> ArrowSampler
345where
346 V: Sample<Output = bool> + Clone + Send + Sync + 'static,
347{
348 Box::new(sampler_choice([
349 f32_array(len.clone(), null.clone()),
350 f64_array(len, null),
351 ]))
352}
353
354pub fn arbitrary_float_array<V>(len: Range<usize>, null: Option<V>) -> ArrowSampler
355where
356 V: Sample<Output = bool> + Clone + Send + Sync + 'static,
357{
358 valid_float_array(len, null)
359}
360
361pub fn arbitrary_int_array<V>(len: Range<usize>, null: Option<V>) -> ArrowSampler
362where
363 V: Sample<Output = bool> + Clone + Send + Sync + 'static,
364{
365 Box::new(sampler_choice([
366 i8_array(len.clone(), null.clone()),
367 i16_array(len.clone(), null.clone()),
368 i32_array(len.clone(), null.clone()),
369 i64_array(len.clone(), null.clone()),
370 ]))
371}
372
373pub fn arbitrary_uint_array<V>(len: Range<usize>, null: Option<V>) -> ArrowSampler
374where
375 V: Sample<Output = bool> + Clone + Send + Sync + 'static,
376{
377 Box::new(sampler_choice([
378 u8_array(len.clone(), null.clone()),
379 u16_array(len.clone(), null.clone()),
380 u32_array(len.clone(), null.clone()),
381 u64_array(len.clone(), null.clone()),
382 ]))
383}
384
385pub fn valid_primitive<V>(len: Range<usize>, null: Option<V>) -> ArrowSampler
386where
387 V: Sample<Output = bool> + Clone + Send + Sync + 'static,
388{
389 Box::new(sampler_choice([
390 valid_float_array(len.clone(), null.clone()),
391 arbitrary_int_array(len.clone(), null.clone()),
392 arbitrary_uint_array(len.clone(), null.clone()),
393 ]))
394}
395
396pub fn arbitrary_primitive<V>(len: Range<usize>, null: Option<V>) -> ArrowSampler
397where
398 V: Sample<Output = bool> + Clone + Send + Sync + 'static,
399{
400 valid_primitive(len, null)
401}
402
403#[cfg(test)]
404mod tests {
405 use sample_std::Chance;
406
407 use super::*;
408
409 #[test]
410 fn gen_float() {
411 let mut gen = valid_float_array(50..51, Some(Chance(0.5)));
412 let mut r = Random::new();
413 let arr = gen.generate(&mut r);
414 assert_eq!(arr.len(), 50);
415 }
416}