Struct arrow2::array::PrimitiveArray
source · pub struct PrimitiveArray<T: NativeType> { /* private fields */ }
Expand description
A PrimitiveArray
is Arrow’s semantically equivalent of an immutable Vec<Option<T>>
where
T is NativeType
(e.g. i32
). It implements Array
.
One way to think about a PrimitiveArray
is (DataType, Arc<Vec<T>>, Option<Arc<Vec<u8>>>)
where:
- the first item is the array’s logical type
- the second is the immutable values
- the third is the immutable validity (whether a value is null or not as a bitmap).
The size of this struct is O(1)
, as all data is stored behind an std::sync::Arc
.
Example
use arrow2::array::PrimitiveArray;
use arrow2::bitmap::Bitmap;
use arrow2::buffer::Buffer;
let array = PrimitiveArray::from([Some(1i32), None, Some(10)]);
assert_eq!(array.value(0), 1);
assert_eq!(array.iter().collect::<Vec<_>>(), vec![Some(&1i32), None, Some(&10)]);
assert_eq!(array.values_iter().copied().collect::<Vec<_>>(), vec![1, 0, 10]);
// the underlying representation
assert_eq!(array.values(), &Buffer::from(vec![1i32, 0, 10]));
assert_eq!(array.validity(), Some(&Bitmap::from([true, false, true])));
Implementations§
source§impl<T: NativeType> PrimitiveArray<T>
impl<T: NativeType> PrimitiveArray<T>
sourcepub fn try_new(
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>
) -> Result<Self, Error>
pub fn try_new(
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>
) -> Result<Self, Error>
The canonical method to create a PrimitiveArray
out of its internal components.
Implementation
This function is O(1)
.
Errors
This function errors iff:
- The validity is not
None
and its length is different fromvalues
’s length - The
data_type
’sPhysicalType
is not equal to [PhysicalType::Primitive(T::PRIMITIVE)
]
Examples found in repository?
More examples
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
unsafe fn try_from_ffi(array: A) -> Result<Self, Error> {
// keys: similar to PrimitiveArray, but the datatype is the inner one
let validity = unsafe { array.validity() }?;
let values = unsafe { array.buffer::<K>(1) }?;
let data_type = array.data_type().clone();
let keys = PrimitiveArray::<K>::try_new(K::PRIMITIVE.into(), values, validity)?;
let values = array
.dictionary()?
.ok_or_else(|| Error::oos("Dictionary Array must contain a dictionary in ffi"))?;
let values = ffi::try_from(values)?;
// the assumption of this trait
DictionaryArray::<K>::try_new_unchecked(data_type, keys, values)
}
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
fn deserialize_float<T: NativeType + decode::Float>(
data_type: DataType,
column: &Column,
) -> Result<PrimitiveArray<T>, Error> {
let mut scratch = vec![];
let num_rows = column.number_of_rows();
let validity = deserialize_validity(column, &mut scratch)?;
let mut chunks = column.get_stream(Kind::Data, scratch)?;
let mut values = Vec::with_capacity(num_rows);
if let Some(validity) = &validity {
let mut items =
decode::FloatIter::<T, _>::new(&mut chunks, validity.len() - validity.unset_bits());
for is_valid in validity {
if is_valid {
values.push(items.next().transpose()?.unwrap_or_default())
} else {
values.push(T::default())
}
}
} else {
let items = decode::FloatIter::<T, _>::new(&mut chunks, num_rows);
for item in items {
values.push(item?);
}
}
PrimitiveArray::try_new(data_type, values.into(), validity)
}
/// Deserializes column `column` from `stripe`, assumed to represent a boolean array
fn deserialize_bool(data_type: DataType, column: &Column) -> Result<BooleanArray, Error> {
let num_rows = column.number_of_rows();
let mut scratch = vec![];
let validity = deserialize_validity(column, &mut scratch)?;
let mut chunks = column.get_stream(Kind::Data, std::mem::take(&mut scratch))?;
let mut values = MutableBitmap::with_capacity(num_rows);
if let Some(validity) = &validity {
let mut items =
decode::BooleanIter::new(&mut chunks, validity.len() - validity.unset_bits());
for is_valid in validity {
values.push(if is_valid {
items.next().transpose()?.unwrap_or_default()
} else {
false
});
}
} else {
let valid_iter = decode::BooleanIter::new(&mut chunks, num_rows);
for v in valid_iter {
values.push(v?)
}
}
BooleanArray::try_new(data_type, values.into(), validity)
}
/// Deserializes column `column` from `stripe`, assumed to represent a boolean array
fn deserialize_i64(data_type: DataType, column: &Column) -> Result<Int64Array, Error> {
let num_rows = column.number_of_rows();
let mut scratch = vec![];
let validity = deserialize_validity(column, &mut scratch)?;
let chunks = column.get_stream(Kind::Data, std::mem::take(&mut scratch))?;
let mut values = Vec::with_capacity(num_rows);
if let Some(validity) = &validity {
let mut iter =
decode::SignedRleV2Iter::new(chunks, validity.len() - validity.unset_bits(), vec![]);
for is_valid in validity {
if is_valid {
let item = iter.next().transpose()?.unwrap_or_default();
values.push(item);
} else {
values.push(0);
}
}
} else {
let mut iter = decode::SignedRleV2RunIter::new(chunks, num_rows, vec![]);
iter.try_for_each(|run| {
run.map(|run| match run {
decode::SignedRleV2Run::Direct(values_iter) => values.extend(values_iter),
decode::SignedRleV2Run::Delta(values_iter) => values.extend(values_iter),
decode::SignedRleV2Run::ShortRepeat(values_iter) => values.extend(values_iter),
})
})?;
}
Int64Array::try_new(data_type, values.into(), validity)
}
/// Deserializes column `column` from `stripe`, assumed to represent a boolean array
fn deserialize_int<T>(data_type: DataType, column: &Column) -> Result<PrimitiveArray<T>, Error>
where
T: NativeType + TryFrom<i64>,
{
let num_rows = column.number_of_rows();
let mut scratch = vec![];
let validity = deserialize_validity(column, &mut scratch)?;
let chunks = column.get_stream(Kind::Data, std::mem::take(&mut scratch))?;
let mut values = Vec::<T>::with_capacity(num_rows);
if let Some(validity) = &validity {
let validity_iter = validity.iter();
let mut iter =
decode::SignedRleV2Iter::new(chunks, validity.len() - validity.unset_bits(), vec![]);
for is_valid in validity_iter {
if is_valid {
let item = iter.next().transpose()?.unwrap_or_default();
let item = item
.try_into()
.map_err(|_| Error::ExternalFormat("value uncastable".to_string()))?;
values.push(item);
} else {
values.push(T::default());
}
}
} else {
let mut iter = decode::SignedRleV2RunIter::new(chunks, num_rows, vec![]);
iter.try_for_each(|run| {
run.map_err(Error::from).and_then(|run| match run {
decode::SignedRleV2Run::Direct(values_iter) => {
for item in values_iter {
let item = item
.try_into()
.map_err(|_| Error::ExternalFormat("value uncastable".to_string()))?;
values.push(item);
}
Ok(())
}
decode::SignedRleV2Run::Delta(values_iter) => {
for item in values_iter {
let item = item
.try_into()
.map_err(|_| Error::ExternalFormat("value uncastable".to_string()))?;
values.push(item);
}
Ok(())
}
decode::SignedRleV2Run::ShortRepeat(values_iter) => {
for item in values_iter {
let item = item
.try_into()
.map_err(|_| Error::ExternalFormat("value uncastable".to_string()))?;
values.push(item);
}
Ok(())
}
})
})?;
}
PrimitiveArray::try_new(data_type, values.into(), validity)
}
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
pub fn read_primitive<T: NativeType, R: Read + Seek>(
field_nodes: &mut VecDeque<Node>,
data_type: DataType,
buffers: &mut VecDeque<IpcBuffer>,
reader: &mut R,
block_offset: u64,
is_little_endian: bool,
compression: Option<Compression>,
limit: Option<usize>,
scratch: &mut Vec<u8>,
) -> Result<PrimitiveArray<T>>
where
Vec<u8>: TryInto<T::Bytes>,
{
let field_node = field_nodes.pop_front().ok_or_else(|| {
Error::oos(format!(
"IPC: unable to fetch the field for {:?}. The file or stream is corrupted.",
data_type
))
})?;
let validity = read_validity(
buffers,
field_node,
reader,
block_offset,
is_little_endian,
compression,
limit,
scratch,
)?;
let length: usize = field_node
.length()
.try_into()
.map_err(|_| Error::from(OutOfSpecKind::NegativeFooterLength))?;
let length = limit.map(|limit| limit.min(length)).unwrap_or(length);
let values = read_buffer(
buffers,
length,
reader,
block_offset,
is_little_endian,
compression,
scratch,
)?;
PrimitiveArray::<T>::try_new(data_type, values, validity)
}
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
pub fn page_iter_to_arrays<'a, I: Pages + 'a>(
pages: I,
type_: &PrimitiveType,
data_type: DataType,
chunk_size: Option<usize>,
num_rows: usize,
) -> Result<ArrayIter<'a>> {
use DataType::*;
let physical_type = &type_.physical_type;
let logical_type = &type_.logical_type;
Ok(match data_type.to_logical_type() {
Null => null::iter_to_arrays(pages, data_type, chunk_size, num_rows),
Boolean => dyn_iter(boolean::Iter::new(pages, data_type, chunk_size, num_rows)),
UInt8 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as u8,
))),
UInt16 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as u16,
))),
UInt32 => match physical_type {
PhysicalType::Int32 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as u32,
))),
// some implementations of parquet write arrow's u32 into i64.
PhysicalType::Int64 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x as u32,
))),
other => {
return Err(Error::NotYetImplemented(format!(
"Reading uin32 from {:?}-encoded parquet still not implemented",
other
)))
}
},
Int8 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as i8,
))),
Int16 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as i16,
))),
Int32 | Date32 | Time32(_) => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x,
))),
Timestamp(time_unit, _) => {
let time_unit = *time_unit;
return timestamp(
pages,
physical_type,
logical_type,
data_type,
num_rows,
chunk_size,
time_unit,
);
}
FixedSizeBinary(_) => dyn_iter(fixed_size_binary::Iter::new(
pages, data_type, num_rows, chunk_size,
)),
Interval(IntervalUnit::YearMonth) => {
let n = 12;
let pages = fixed_size_binary::Iter::new(
pages,
DataType::FixedSizeBinary(n),
num_rows,
chunk_size,
);
let pages = pages.map(move |maybe_array| {
let array = maybe_array?;
let values = array
.values()
.chunks_exact(n)
.map(|value: &[u8]| i32::from_le_bytes(value[..4].try_into().unwrap()))
.collect::<Vec<_>>();
let validity = array.validity().cloned();
PrimitiveArray::<i32>::try_new(data_type.clone(), values.into(), validity)
});
let arrays = pages.map(|x| x.map(|x| x.boxed()));
Box::new(arrays) as _
}
Interval(IntervalUnit::DayTime) => {
let n = 12;
let pages = fixed_size_binary::Iter::new(
pages,
DataType::FixedSizeBinary(n),
num_rows,
chunk_size,
);
let pages = pages.map(move |maybe_array| {
let array = maybe_array?;
let values = array
.values()
.chunks_exact(n)
.map(super::super::convert_days_ms)
.collect::<Vec<_>>();
let validity = array.validity().cloned();
PrimitiveArray::<days_ms>::try_new(data_type.clone(), values.into(), validity)
});
let arrays = pages.map(|x| x.map(|x| x.boxed()));
Box::new(arrays) as _
}
Decimal(_, _) => match physical_type {
PhysicalType::Int32 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as i128,
))),
PhysicalType::Int64 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x as i128,
))),
PhysicalType::FixedLenByteArray(n) if *n > 16 => {
return Err(Error::NotYetImplemented(format!(
"Can't decode Decimal128 type from Fixed Size Byte Array of len {:?}",
n
)))
}
PhysicalType::FixedLenByteArray(n) => {
let n = *n;
let pages = fixed_size_binary::Iter::new(
pages,
DataType::FixedSizeBinary(n),
num_rows,
chunk_size,
);
let pages = pages.map(move |maybe_array| {
let array = maybe_array?;
let values = array
.values()
.chunks_exact(n)
.map(|value: &[u8]| super::super::convert_i128(value, n))
.collect::<Vec<_>>();
let validity = array.validity().cloned();
PrimitiveArray::<i128>::try_new(data_type.clone(), values.into(), validity)
});
let arrays = pages.map(|x| x.map(|x| x.boxed()));
Box::new(arrays) as _
}
_ => unreachable!(),
},
// INT64
Int64 | Date64 | Time64(_) | Duration(_) => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x,
))),
UInt64 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x as u64,
))),
Float32 => dyn_iter(iden(primitive::Iter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: f32| x,
))),
Float64 => dyn_iter(iden(primitive::Iter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: f64| x,
))),
Binary => dyn_iter(binary::Iter::<i32, BinaryArray<i32>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
LargeBinary => dyn_iter(binary::Iter::<i64, BinaryArray<i64>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
Utf8 => dyn_iter(binary::Iter::<i32, Utf8Array<i32>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
LargeUtf8 => dyn_iter(binary::Iter::<i64, Utf8Array<i64>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
Dictionary(key_type, _, _) => {
return match_integer_type!(key_type, |$K| {
dict_read::<$K, _>(pages, physical_type, logical_type, data_type, num_rows, chunk_size)
})
}
other => {
return Err(Error::NotYetImplemented(format!(
"Reading {:?} from parquet still not implemented",
other
)))
}
})
}
sourcepub fn to(self, data_type: DataType) -> Self
pub fn to(self, data_type: DataType) -> Self
Returns a new PrimitiveArray
with a different logical type.
This function is useful to assign a different DataType
to the array.
Used to change the arrays’ logical type (see example).
Example
use arrow2::array::Int32Array;
use arrow2::datatypes::DataType;
let array = Int32Array::from(&[Some(1), None, Some(2)]).to(DataType::Date32);
assert_eq!(
format!("{:?}", array),
"Date32[1970-01-02, None, 1970-01-03]"
);
Panics
Panics iff the data_type
’s PhysicalType
is not equal to [PhysicalType::Primitive(T::PRIMITIVE)
]
Examples found in repository?
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
pub fn utf8_to_primitive<O: Offset, T>(from: &Utf8Array<O>, to: &DataType) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from
.iter()
.map(|x| x.and_then::<T, _>(|x| lexical_core::parse(x.as_bytes()).ok()));
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
/// Casts a [`Utf8Array`] to a [`PrimitiveArray`] at best-effort using `lexical_core::parse_partial`, making any uncastable value as zero.
pub fn partial_utf8_to_primitive<O: Offset, T>(
from: &Utf8Array<O>,
to: &DataType,
) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from.iter().map(|x| {
x.and_then::<T, _>(|x| lexical_core::parse_partial(x.as_bytes()).ok().map(|x| x.0))
});
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
pub(super) fn utf8_to_primitive_dyn<O: Offset, T>(
from: &dyn Array,
to: &DataType,
options: CastOptions,
) -> Result<Box<dyn Array>>
where
T: NativeType + lexical_core::FromLexical,
{
let from = from.as_any().downcast_ref().unwrap();
if options.partial {
Ok(Box::new(partial_utf8_to_primitive::<O, T>(from, to)))
} else {
Ok(Box::new(utf8_to_primitive::<O, T>(from, to)))
}
}
/// Casts a [`Utf8Array`] to a Date32 primitive, making any uncastable value a Null.
pub fn utf8_to_date32<O: Offset>(from: &Utf8Array<O>) -> PrimitiveArray<i32> {
let iter = from.iter().map(|x| {
x.and_then(|x| {
x.parse::<chrono::NaiveDate>()
.ok()
.map(|x| x.num_days_from_ce() - EPOCH_DAYS_FROM_CE)
})
});
PrimitiveArray::<i32>::from_trusted_len_iter(iter).to(DataType::Date32)
}
pub(super) fn utf8_to_date32_dyn<O: Offset>(from: &dyn Array) -> Result<Box<dyn Array>> {
let from = from.as_any().downcast_ref().unwrap();
Ok(Box::new(utf8_to_date32::<O>(from)))
}
/// Casts a [`Utf8Array`] to a Date64 primitive, making any uncastable value a Null.
pub fn utf8_to_date64<O: Offset>(from: &Utf8Array<O>) -> PrimitiveArray<i64> {
let iter = from.iter().map(|x| {
x.and_then(|x| {
x.parse::<chrono::NaiveDate>()
.ok()
.map(|x| (x.num_days_from_ce() - EPOCH_DAYS_FROM_CE) as i64 * 86400000)
})
});
PrimitiveArray::from_trusted_len_iter(iter).to(DataType::Date64)
}
More examples
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
pub fn partial_binary_to_primitive<O: Offset, T>(
from: &BinaryArray<O>,
to: &DataType,
) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from
.iter()
.map(|x| x.and_then::<T, _>(|x| lexical_core::parse_partial(x).ok().map(|x| x.0)));
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
/// Casts a [`BinaryArray`] to a [`PrimitiveArray`], making any uncastable value a Null.
pub fn binary_to_primitive<O: Offset, T>(from: &BinaryArray<O>, to: &DataType) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from
.iter()
.map(|x| x.and_then::<T, _>(|x| lexical_core::parse(x).ok()));
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
pub fn primitive_to_primitive<I, O>(
from: &PrimitiveArray<I>,
to_type: &DataType,
) -> PrimitiveArray<O>
where
I: NativeType + num_traits::NumCast,
O: NativeType + num_traits::NumCast,
{
let iter = from
.iter()
.map(|v| v.and_then(|x| num_traits::cast::cast::<I, O>(*x)));
PrimitiveArray::<O>::from_trusted_len_iter(iter).to(to_type.clone())
}
/// Returns a [`PrimitiveArray<i128>`] with the casted values. Values are `None` on overflow
pub fn integer_to_decimal<T: NativeType + AsPrimitive<i128>>(
from: &PrimitiveArray<T>,
to_precision: usize,
to_scale: usize,
) -> PrimitiveArray<i128> {
let multiplier = 10_i128.pow(to_scale as u32);
let min_for_precision = 9_i128
.saturating_pow(1 + to_precision as u32)
.saturating_neg();
let max_for_precision = 9_i128.saturating_pow(1 + to_precision as u32);
let values = from.iter().map(|x| {
x.and_then(|x| {
x.as_().checked_mul(multiplier).and_then(|x| {
if x > max_for_precision || x < min_for_precision {
None
} else {
Some(x)
}
})
})
});
PrimitiveArray::<i128>::from_trusted_len_iter(values)
.to(DataType::Decimal(to_precision, to_scale))
}
pub(super) fn integer_to_decimal_dyn<T>(
from: &dyn Array,
precision: usize,
scale: usize,
) -> Result<Box<dyn Array>>
where
T: NativeType + AsPrimitive<i128>,
{
let from = from.as_any().downcast_ref().unwrap();
Ok(Box::new(integer_to_decimal::<T>(from, precision, scale)))
}
/// Returns a [`PrimitiveArray<i128>`] with the casted values. Values are `None` on overflow
pub fn float_to_decimal<T>(
from: &PrimitiveArray<T>,
to_precision: usize,
to_scale: usize,
) -> PrimitiveArray<i128>
where
T: NativeType + Float + ToPrimitive,
f64: AsPrimitive<T>,
{
// 1.2 => 12
let multiplier: T = (10_f64).powi(to_scale as i32).as_();
let min_for_precision = 9_i128
.saturating_pow(1 + to_precision as u32)
.saturating_neg();
let max_for_precision = 9_i128.saturating_pow(1 + to_precision as u32);
let values = from.iter().map(|x| {
x.and_then(|x| {
let x = (*x * multiplier).to_i128().unwrap();
if x > max_for_precision || x < min_for_precision {
None
} else {
Some(x)
}
})
});
PrimitiveArray::<i128>::from_trusted_len_iter(values)
.to(DataType::Decimal(to_precision, to_scale))
}
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
fn utf8_to_timestamp_ns_impl<O: Offset, T: chrono::TimeZone>(
array: &Utf8Array<O>,
fmt: &str,
timezone: String,
tz: T,
) -> PrimitiveArray<i64> {
let iter = array
.iter()
.map(|x| x.and_then(|x| utf8_to_timestamp_ns_scalar(x, fmt, &tz)));
PrimitiveArray::from_trusted_len_iter(iter)
.to(DataType::Timestamp(TimeUnit::Nanosecond, Some(timezone)))
}
/// Parses `value` to a [`chrono_tz::Tz`] with the Arrow's definition of timestamp with a timezone.
#[cfg(feature = "chrono-tz")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-tz")))]
pub fn parse_offset_tz(timezone: &str) -> Result<chrono_tz::Tz> {
timezone.parse::<chrono_tz::Tz>().map_err(|_| {
Error::InvalidArgumentError(format!("timezone \"{}\" cannot be parsed", timezone))
})
}
#[cfg(feature = "chrono-tz")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-tz")))]
fn chrono_tz_utf_to_timestamp_ns<O: Offset>(
array: &Utf8Array<O>,
fmt: &str,
timezone: String,
) -> Result<PrimitiveArray<i64>> {
let tz = parse_offset_tz(&timezone)?;
Ok(utf8_to_timestamp_ns_impl(array, fmt, timezone, tz))
}
#[cfg(not(feature = "chrono-tz"))]
fn chrono_tz_utf_to_timestamp_ns<O: Offset>(
_: &Utf8Array<O>,
_: &str,
timezone: String,
) -> Result<PrimitiveArray<i64>> {
Err(Error::InvalidArgumentError(format!(
"timezone \"{}\" cannot be parsed (feature chrono-tz is not active)",
timezone
)))
}
/// Parses a [`Utf8Array`] to a timeozone-aware timestamp, i.e. [`PrimitiveArray<i64>`] with type `Timestamp(Nanosecond, Some(timezone))`.
/// # Implementation
/// * parsed values with timezone other than `timezone` are converted to `timezone`.
/// * parsed values without timezone are null. Use [`utf8_to_naive_timestamp_ns`] to parse naive timezones.
/// * Null elements remain null; non-parsable elements are null.
/// The feature `"chrono-tz"` enables IANA and zoneinfo formats for `timezone`.
/// # Error
/// This function errors iff `timezone` is not parsable to an offset.
pub fn utf8_to_timestamp_ns<O: Offset>(
array: &Utf8Array<O>,
fmt: &str,
timezone: String,
) -> Result<PrimitiveArray<i64>> {
let tz = parse_offset(timezone.as_str());
if let Ok(tz) = tz {
Ok(utf8_to_timestamp_ns_impl(array, fmt, timezone, tz))
} else {
chrono_tz_utf_to_timestamp_ns(array, fmt, timezone)
}
}
/// Parses a [`Utf8Array`] to naive timestamp, i.e.
/// [`PrimitiveArray<i64>`] with type `Timestamp(Nanosecond, None)`.
/// Timezones are ignored.
/// Null elements remain null; non-parsable elements are set to null.
pub fn utf8_to_naive_timestamp_ns<O: Offset>(
array: &Utf8Array<O>,
fmt: &str,
) -> PrimitiveArray<i64> {
let iter = array
.iter()
.map(|x| x.and_then(|x| utf8_to_naive_timestamp_ns_scalar(x, fmt)));
PrimitiveArray::from_trusted_len_iter(iter).to(DataType::Timestamp(TimeUnit::Nanosecond, None))
}
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
fn deserialize_primitive<T, B: ByteRecordGeneric, F>(
rows: &[B],
column: usize,
datatype: DataType,
op: F,
) -> Box<dyn Array>
where
T: NativeType + lexical_core::FromLexical,
F: Fn(&[u8]) -> Option<T>,
{
let iter = rows.iter().map(|row| match row.get(column) {
Some(bytes) => {
if bytes.is_empty() {
return None;
}
op(bytes)
}
None => None,
});
Box::new(PrimitiveArray::<T>::from_trusted_len_iter(iter).to(datatype))
}
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
pub fn div<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + Div<Output = T>,
{
if rhs.null_count() == 0 {
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a / b)
} else {
check_same_len(lhs, rhs).unwrap();
let values = lhs.iter().zip(rhs.iter()).map(|(l, r)| match (l, r) {
(Some(l), Some(r)) => Some(*l / *r),
_ => None,
});
PrimitiveArray::from_trusted_len_iter(values).to(lhs.data_type().clone())
}
}
sourcepub fn from_vec(values: Vec<T>) -> Self
pub fn from_vec(values: Vec<T>) -> Self
Creates a (non-null) PrimitiveArray
from a vector of values.
This function is O(1)
.
Examples
use arrow2::array::PrimitiveArray;
let array = PrimitiveArray::from_vec(vec![1, 2, 3]);
assert_eq!(format!("{:?}", array), "Int32[1, 2, 3]");
sourcepub fn iter(&self) -> ZipValidity<&T, Iter<'_, T>, BitmapIter<'_>> ⓘ
pub fn iter(&self) -> ZipValidity<&T, Iter<'_, T>, BitmapIter<'_>> ⓘ
Returns an iterator over the values and validity, Option<&T>
.
Examples found in repository?
More examples
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
fn primitive_write<'a, T: NativeType + ToLexical>(
array: &'a PrimitiveArray<T>,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a> {
Box::new(BufStreamingIterator::new(
array.iter(),
|x, buf| {
if let Some(x) = x {
lexical_to_bytes_mut(*x, buf)
}
},
vec![],
))
}
macro_rules! dyn_primitive {
($ty:ty, $array:expr) => {{
let array = $array.as_any().downcast_ref().unwrap();
primitive_write::<$ty>(array)
}};
}
macro_rules! dyn_date {
($ty:ident, $fn:expr, $array:expr, $format:expr) => {{
let array = $array
.as_any()
.downcast_ref::<PrimitiveArray<$ty>>()
.unwrap();
if let Some(format) = $format {
Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let dt = ($fn)(*x).format(format);
let _ = write!(StringWrap(buf), "{}", dt);
}
},
vec![],
))
} else {
Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let dt = ($fn)(*x);
let _ = write!(StringWrap(buf), "{}", dt);
}
},
vec![],
))
}
}};
}
fn timestamp_with_tz_default<'a>(
array: &'a PrimitiveArray<i64>,
time_unit: TimeUnit,
tz: &str,
) -> Result<Box<dyn StreamingIterator<Item = [u8]> + 'a>> {
let timezone = temporal_conversions::parse_offset(tz);
Ok(match timezone {
Ok(timezone) => Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let dt = temporal_conversions::timestamp_to_datetime(*x, time_unit, &timezone);
let _ = write!(StringWrap(buf), "{}", dt);
}
},
vec![],
)),
#[cfg(feature = "chrono-tz")]
_ => {
let timezone = temporal_conversions::parse_offset_tz(tz)?;
Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let dt =
temporal_conversions::timestamp_to_datetime(*x, time_unit, &timezone);
let _ = write!(StringWrap(buf), "{}", dt);
}
},
vec![],
))
}
#[cfg(not(feature = "chrono-tz"))]
_ => {
return Err(crate::error::Error::InvalidArgumentError(
"Invalid Offset format (must be [-]00:00) or chrono-tz feature not active"
.to_string(),
))
}
})
}
fn timestamp_with_tz_with_format<'a>(
array: &'a PrimitiveArray<i64>,
time_unit: TimeUnit,
tz: &str,
format: &'a str,
) -> Result<Box<dyn StreamingIterator<Item = [u8]> + 'a>> {
let timezone = temporal_conversions::parse_offset(tz);
Ok(match timezone {
Ok(timezone) => Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let dt = temporal_conversions::timestamp_to_datetime(*x, time_unit, &timezone)
.format(format);
let _ = write!(StringWrap(buf), "{}", dt);
}
},
vec![],
)),
#[cfg(feature = "chrono-tz")]
_ => {
let timezone = temporal_conversions::parse_offset_tz(tz)?;
Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let dt =
temporal_conversions::timestamp_to_datetime(*x, time_unit, &timezone)
.format(format);
let _ = write!(StringWrap(buf), "{}", dt);
}
},
vec![],
))
}
#[cfg(not(feature = "chrono-tz"))]
_ => {
return Err(crate::error::Error::InvalidArgumentError(
"Invalid Offset format (must be [-]00:00) or chrono-tz feature not active"
.to_string(),
))
}
})
}
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
pub fn primitive_to_primitive<I, O>(
from: &PrimitiveArray<I>,
to_type: &DataType,
) -> PrimitiveArray<O>
where
I: NativeType + num_traits::NumCast,
O: NativeType + num_traits::NumCast,
{
let iter = from
.iter()
.map(|v| v.and_then(|x| num_traits::cast::cast::<I, O>(*x)));
PrimitiveArray::<O>::from_trusted_len_iter(iter).to(to_type.clone())
}
/// Returns a [`PrimitiveArray<i128>`] with the casted values. Values are `None` on overflow
pub fn integer_to_decimal<T: NativeType + AsPrimitive<i128>>(
from: &PrimitiveArray<T>,
to_precision: usize,
to_scale: usize,
) -> PrimitiveArray<i128> {
let multiplier = 10_i128.pow(to_scale as u32);
let min_for_precision = 9_i128
.saturating_pow(1 + to_precision as u32)
.saturating_neg();
let max_for_precision = 9_i128.saturating_pow(1 + to_precision as u32);
let values = from.iter().map(|x| {
x.and_then(|x| {
x.as_().checked_mul(multiplier).and_then(|x| {
if x > max_for_precision || x < min_for_precision {
None
} else {
Some(x)
}
})
})
});
PrimitiveArray::<i128>::from_trusted_len_iter(values)
.to(DataType::Decimal(to_precision, to_scale))
}
pub(super) fn integer_to_decimal_dyn<T>(
from: &dyn Array,
precision: usize,
scale: usize,
) -> Result<Box<dyn Array>>
where
T: NativeType + AsPrimitive<i128>,
{
let from = from.as_any().downcast_ref().unwrap();
Ok(Box::new(integer_to_decimal::<T>(from, precision, scale)))
}
/// Returns a [`PrimitiveArray<i128>`] with the casted values. Values are `None` on overflow
pub fn float_to_decimal<T>(
from: &PrimitiveArray<T>,
to_precision: usize,
to_scale: usize,
) -> PrimitiveArray<i128>
where
T: NativeType + Float + ToPrimitive,
f64: AsPrimitive<T>,
{
// 1.2 => 12
let multiplier: T = (10_f64).powi(to_scale as i32).as_();
let min_for_precision = 9_i128
.saturating_pow(1 + to_precision as u32)
.saturating_neg();
let max_for_precision = 9_i128.saturating_pow(1 + to_precision as u32);
let values = from.iter().map(|x| {
x.and_then(|x| {
let x = (*x * multiplier).to_i128().unwrap();
if x > max_for_precision || x < min_for_precision {
None
} else {
Some(x)
}
})
});
PrimitiveArray::<i128>::from_trusted_len_iter(values)
.to(DataType::Decimal(to_precision, to_scale))
}
pub(super) fn float_to_decimal_dyn<T>(
from: &dyn Array,
precision: usize,
scale: usize,
) -> Result<Box<dyn Array>>
where
T: NativeType + Float + ToPrimitive,
f64: AsPrimitive<T>,
{
let from = from.as_any().downcast_ref().unwrap();
Ok(Box::new(float_to_decimal::<T>(from, precision, scale)))
}
/// Cast [`PrimitiveArray`] as a [`PrimitiveArray`]
/// Same as `number as to_number_type` in rust
pub fn primitive_as_primitive<I, O>(
from: &PrimitiveArray<I>,
to_type: &DataType,
) -> PrimitiveArray<O>
where
I: NativeType + num_traits::AsPrimitive<O>,
O: NativeType,
{
unary(from, num_traits::AsPrimitive::<O>::as_, to_type.clone())
}
/// Cast [`PrimitiveArray`] to a [`PrimitiveArray`] of the same physical type.
/// This is O(1).
pub fn primitive_to_same_primitive<T>(
from: &PrimitiveArray<T>,
to_type: &DataType,
) -> PrimitiveArray<T>
where
T: NativeType,
{
PrimitiveArray::<T>::new(
to_type.clone(),
from.values().clone(),
from.validity().cloned(),
)
}
/// Cast [`PrimitiveArray`] to a [`PrimitiveArray`] of the same physical type.
/// This is O(1).
pub(super) fn primitive_to_same_primitive_dyn<T>(
from: &dyn Array,
to_type: &DataType,
) -> Result<Box<dyn Array>>
where
T: NativeType,
{
let from = from.as_any().downcast_ref().unwrap();
Ok(Box::new(primitive_to_same_primitive::<T>(from, to_type)))
}
pub(super) fn primitive_to_dictionary_dyn<T: NativeType + Eq + Hash, K: DictionaryKey>(
from: &dyn Array,
) -> Result<Box<dyn Array>> {
let from = from.as_any().downcast_ref().unwrap();
primitive_to_dictionary::<T, K>(from).map(|x| Box::new(x) as Box<dyn Array>)
}
/// Cast [`PrimitiveArray`] to [`DictionaryArray`]. Also known as packing.
/// # Errors
/// This function errors if the maximum key is smaller than the number of distinct elements
/// in the array.
pub fn primitive_to_dictionary<T: NativeType + Eq + Hash, K: DictionaryKey>(
from: &PrimitiveArray<T>,
) -> Result<DictionaryArray<K>> {
let iter = from.iter().map(|x| x.copied());
let mut array = MutableDictionaryArray::<K, _>::from(MutablePrimitiveArray::<T>::from(
from.data_type().clone(),
));
array.try_extend(iter)?;
Ok(array.into())
}
/// Get the time unit as a multiple of a second
const fn time_unit_multiple(unit: TimeUnit) -> i64 {
match unit {
TimeUnit::Second => 1,
TimeUnit::Millisecond => MILLISECONDS,
TimeUnit::Microsecond => MICROSECONDS,
TimeUnit::Nanosecond => NANOSECONDS,
}
}
/// Conversion of dates
pub fn date32_to_date64(from: &PrimitiveArray<i32>) -> PrimitiveArray<i64> {
unary(from, |x| x as i64 * MILLISECONDS_IN_DAY, DataType::Date64)
}
/// Conversion of dates
pub fn date64_to_date32(from: &PrimitiveArray<i64>) -> PrimitiveArray<i32> {
unary(from, |x| (x / MILLISECONDS_IN_DAY) as i32, DataType::Date32)
}
/// Conversion of times
pub fn time32s_to_time32ms(from: &PrimitiveArray<i32>) -> PrimitiveArray<i32> {
unary(from, |x| x * 1000, DataType::Time32(TimeUnit::Millisecond))
}
/// Conversion of times
pub fn time32ms_to_time32s(from: &PrimitiveArray<i32>) -> PrimitiveArray<i32> {
unary(from, |x| x / 1000, DataType::Time32(TimeUnit::Second))
}
/// Conversion of times
pub fn time64us_to_time64ns(from: &PrimitiveArray<i64>) -> PrimitiveArray<i64> {
unary(from, |x| x * 1000, DataType::Time64(TimeUnit::Nanosecond))
}
/// Conversion of times
pub fn time64ns_to_time64us(from: &PrimitiveArray<i64>) -> PrimitiveArray<i64> {
unary(from, |x| x / 1000, DataType::Time64(TimeUnit::Microsecond))
}
/// Conversion of timestamp
pub fn timestamp_to_date64(from: &PrimitiveArray<i64>, from_unit: TimeUnit) -> PrimitiveArray<i64> {
let from_size = time_unit_multiple(from_unit);
let to_size = MILLISECONDS;
let to_type = DataType::Date64;
// Scale time_array by (to_size / from_size) using a
// single integer operation, but need to avoid integer
// math rounding down to zero
match to_size.cmp(&from_size) {
std::cmp::Ordering::Less => unary(from, |x| (x / (from_size / to_size)), to_type),
std::cmp::Ordering::Equal => primitive_to_same_primitive(from, &to_type),
std::cmp::Ordering::Greater => unary(from, |x| (x * (to_size / from_size)), to_type),
}
}
/// Conversion of timestamp
pub fn timestamp_to_date32(from: &PrimitiveArray<i64>, from_unit: TimeUnit) -> PrimitiveArray<i32> {
let from_size = time_unit_multiple(from_unit) * SECONDS_IN_DAY;
unary(from, |x| (x / from_size) as i32, DataType::Date32)
}
/// Conversion of time
pub fn time32_to_time64(
from: &PrimitiveArray<i32>,
from_unit: TimeUnit,
to_unit: TimeUnit,
) -> PrimitiveArray<i64> {
let from_size = time_unit_multiple(from_unit);
let to_size = time_unit_multiple(to_unit);
let divisor = to_size / from_size;
unary(from, |x| (x as i64 * divisor), DataType::Time64(to_unit))
}
/// Conversion of time
pub fn time64_to_time32(
from: &PrimitiveArray<i64>,
from_unit: TimeUnit,
to_unit: TimeUnit,
) -> PrimitiveArray<i32> {
let from_size = time_unit_multiple(from_unit);
let to_size = time_unit_multiple(to_unit);
let divisor = from_size / to_size;
unary(from, |x| (x / divisor) as i32, DataType::Time32(to_unit))
}
/// Conversion of timestamp
pub fn timestamp_to_timestamp(
from: &PrimitiveArray<i64>,
from_unit: TimeUnit,
to_unit: TimeUnit,
tz: &Option<String>,
) -> PrimitiveArray<i64> {
let from_size = time_unit_multiple(from_unit);
let to_size = time_unit_multiple(to_unit);
let to_type = DataType::Timestamp(to_unit, tz.clone());
// we either divide or multiply, depending on size of each unit
if from_size >= to_size {
unary(from, |x| (x / (from_size / to_size)), to_type)
} else {
unary(from, |x| (x * (to_size / from_size)), to_type)
}
}
fn timestamp_to_utf8_impl<O: Offset, T: chrono::TimeZone>(
from: &PrimitiveArray<i64>,
time_unit: TimeUnit,
timezone: T,
) -> Utf8Array<O>
where
T::Offset: std::fmt::Display,
{
match time_unit {
TimeUnit::Nanosecond => {
let iter = from.iter().map(|x| {
x.map(|x| {
let datetime = timestamp_ns_to_datetime(*x);
let offset = timezone.offset_from_utc_datetime(&datetime);
chrono::DateTime::<T>::from_utc(datetime, offset).to_rfc3339()
})
});
Utf8Array::from_trusted_len_iter(iter)
}
TimeUnit::Microsecond => {
let iter = from.iter().map(|x| {
x.map(|x| {
let datetime = timestamp_us_to_datetime(*x);
let offset = timezone.offset_from_utc_datetime(&datetime);
chrono::DateTime::<T>::from_utc(datetime, offset).to_rfc3339()
})
});
Utf8Array::from_trusted_len_iter(iter)
}
TimeUnit::Millisecond => {
let iter = from.iter().map(|x| {
x.map(|x| {
let datetime = timestamp_ms_to_datetime(*x);
let offset = timezone.offset_from_utc_datetime(&datetime);
chrono::DateTime::<T>::from_utc(datetime, offset).to_rfc3339()
})
});
Utf8Array::from_trusted_len_iter(iter)
}
TimeUnit::Second => {
let iter = from.iter().map(|x| {
x.map(|x| {
let datetime = timestamp_s_to_datetime(*x);
let offset = timezone.offset_from_utc_datetime(&datetime);
chrono::DateTime::<T>::from_utc(datetime, offset).to_rfc3339()
})
});
Utf8Array::from_trusted_len_iter(iter)
}
}
}
#[cfg(feature = "chrono-tz")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-tz")))]
fn chrono_tz_timestamp_to_utf8<O: Offset>(
from: &PrimitiveArray<i64>,
time_unit: TimeUnit,
timezone_str: &str,
) -> Result<Utf8Array<O>> {
let timezone = parse_offset_tz(timezone_str)?;
Ok(timestamp_to_utf8_impl::<O, chrono_tz::Tz>(
from, time_unit, timezone,
))
}
#[cfg(not(feature = "chrono-tz"))]
fn chrono_tz_timestamp_to_utf8<O: Offset>(
_: &PrimitiveArray<i64>,
_: TimeUnit,
timezone_str: &str,
) -> Result<Utf8Array<O>> {
use crate::error::Error;
Err(Error::InvalidArgumentError(format!(
"timezone \"{}\" cannot be parsed (feature chrono-tz is not active)",
timezone_str
)))
}
/// Returns a [`Utf8Array`] where every element is the utf8 representation of the timestamp in the rfc3339 format.
pub fn timestamp_to_utf8<O: Offset>(
from: &PrimitiveArray<i64>,
time_unit: TimeUnit,
timezone_str: &str,
) -> Result<Utf8Array<O>> {
let timezone = parse_offset(timezone_str);
if let Ok(timezone) = timezone {
Ok(timestamp_to_utf8_impl::<O, chrono::FixedOffset>(
from, time_unit, timezone,
))
} else {
chrono_tz_timestamp_to_utf8(from, time_unit, timezone_str)
}
}
/// Returns a [`Utf8Array`] where every element is the utf8 representation of the timestamp in the rfc3339 format.
pub fn naive_timestamp_to_utf8<O: Offset>(
from: &PrimitiveArray<i64>,
time_unit: TimeUnit,
) -> Utf8Array<O> {
match time_unit {
TimeUnit::Nanosecond => {
let iter = from.iter().map(|x| {
x.copied()
.map(timestamp_ns_to_datetime)
.map(|x| x.to_string())
});
Utf8Array::from_trusted_len_iter(iter)
}
TimeUnit::Microsecond => {
let iter = from.iter().map(|x| {
x.copied()
.map(timestamp_us_to_datetime)
.map(|x| x.to_string())
});
Utf8Array::from_trusted_len_iter(iter)
}
TimeUnit::Millisecond => {
let iter = from.iter().map(|x| {
x.copied()
.map(timestamp_ms_to_datetime)
.map(|x| x.to_string())
});
Utf8Array::from_trusted_len_iter(iter)
}
TimeUnit::Second => {
let iter = from.iter().map(|x| {
x.copied()
.map(timestamp_s_to_datetime)
.map(|x| x.to_string())
});
Utf8Array::from_trusted_len_iter(iter)
}
}
}
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
fn primitive_serializer<'a, T: NativeType + ToLexical>(
array: &'a PrimitiveArray<T>,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync> {
Box::new(BufStreamingIterator::new(
array.iter(),
|x, buf| {
if let Some(x) = x {
lexical_to_bytes_mut(*x, buf)
} else {
buf.extend(b"null")
}
},
vec![],
))
}
fn float_serializer<'a, T>(
array: &'a PrimitiveArray<T>,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync>
where
T: num_traits::Float + NativeType + ToLexical,
{
Box::new(BufStreamingIterator::new(
array.iter(),
|x, buf| {
if let Some(x) = x {
if T::is_nan(*x) {
buf.extend(b"null")
} else {
lexical_to_bytes_mut(*x, buf)
}
} else {
buf.extend(b"null")
}
},
vec![],
))
}
fn utf8_serializer<'a, O: Offset>(
array: &'a Utf8Array<O>,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync> {
Box::new(BufStreamingIterator::new(
array.iter(),
|x, buf| {
if let Some(x) = x {
utf8::write_str(buf, x).unwrap();
} else {
buf.extend_from_slice(b"null")
}
},
vec![],
))
}
fn struct_serializer<'a>(
array: &'a StructArray,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync> {
// {"a": [1, 2, 3], "b": [a, b, c], "c": {"a": [1, 2, 3]}}
// [
// {"a": 1, "b": a, "c": {"a": 1}},
// {"a": 2, "b": b, "c": {"a": 2}},
// {"a": 3, "b": c, "c": {"a": 3}},
// ]
//
let mut serializers = array
.values()
.iter()
.map(|x| x.as_ref())
.map(new_serializer)
.collect::<Vec<_>>();
let names = array.fields().iter().map(|f| f.name.as_str());
Box::new(BufStreamingIterator::new(
ZipValidity::new_with_validity(0..array.len(), array.validity()),
move |maybe, buf| {
if maybe.is_some() {
let names = names.clone();
let mut record: Vec<(&str, &[u8])> = Default::default();
serializers
.iter_mut()
.zip(names)
// `unwrap` is infalible because `array.len()` equals `len` on `Chunk`
.for_each(|(iter, name)| {
let item = iter.next().unwrap();
record.push((name, item));
});
serialize_item(buf, &record, true);
} else {
serializers.iter_mut().for_each(|iter| {
let _ = iter.next();
});
buf.extend(b"null");
}
},
vec![],
))
}
fn list_serializer<'a, O: Offset>(
array: &'a ListArray<O>,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync> {
// [[1, 2], [3]]
// [
// [1, 2],
// [3]
// ]
//
let mut serializer = new_serializer(array.values().as_ref());
Box::new(BufStreamingIterator::new(
ZipValidity::new_with_validity(array.offsets().buffer().windows(2), array.validity()),
move |offset, buf| {
if let Some(offset) = offset {
let length = (offset[1] - offset[0]).to_usize();
buf.push(b'[');
let mut is_first_row = true;
for _ in 0..length {
if !is_first_row {
buf.push(b',');
}
is_first_row = false;
buf.extend(serializer.next().unwrap());
}
buf.push(b']');
} else {
buf.extend(b"null");
}
},
vec![],
))
}
fn fixed_size_list_serializer<'a>(
array: &'a FixedSizeListArray,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync> {
let mut serializer = new_serializer(array.values().as_ref());
Box::new(BufStreamingIterator::new(
ZipValidity::new(0..array.len(), array.validity().map(|x| x.iter())),
move |ix, buf| {
if ix.is_some() {
let length = array.size();
buf.push(b'[');
let mut is_first_row = true;
for _ in 0..length {
if !is_first_row {
buf.push(b',');
}
is_first_row = false;
buf.extend(serializer.next().unwrap());
}
buf.push(b']');
} else {
buf.extend(b"null");
}
},
vec![],
))
}
fn date_serializer<'a, T, F>(
array: &'a PrimitiveArray<T>,
convert: F,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync>
where
T: NativeType,
F: Fn(T) -> NaiveDate + 'static + Send + Sync,
{
Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let nd = convert(*x);
write!(buf, "\"{}\"", nd).unwrap();
} else {
buf.extend_from_slice(b"null")
}
},
vec![],
))
}
fn timestamp_serializer<'a, F>(
array: &'a PrimitiveArray<i64>,
convert: F,
) -> Box<dyn StreamingIterator<Item = [u8]> + 'a + Send + Sync>
where
F: Fn(i64) -> NaiveDateTime + 'static + Send + Sync,
{
Box::new(BufStreamingIterator::new(
array.iter(),
move |x, buf| {
if let Some(x) = x {
let ndt = convert(*x);
write!(buf, "\"{}\"", ndt).unwrap();
} else {
buf.extend_from_slice(b"null")
}
},
vec![],
))
}
- src/compute/arithmetics/basic/div.rs
- src/io/parquet/write/fixed_len_bytes.rs
- src/compute/take/boolean.rs
- src/compute/take/primitive.rs
- src/compute/cast/decimal_to.rs
- src/io/parquet/write/primitive/basic.rs
- src/compute/take/structure.rs
- src/compute/contains.rs
- src/io/json_integration/write/array.rs
- src/compute/take/generic_binary.rs
- src/io/avro/write/serialize.rs
sourcepub fn values_iter(&self) -> Iter<'_, T>
pub fn values_iter(&self) -> Iter<'_, T>
Returns an iterator of the values, &T
, ignoring the arrays’ validity.
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the length of this array
Examples found in repository?
More examples
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
pub fn slice(&self, offset: usize, length: usize) -> Self {
assert!(
offset + length <= self.len(),
"offset + length may not exceed length of array"
);
unsafe { self.slice_unchecked(offset, length) }
}
/// Returns a clone of this [`PrimitiveArray`] sliced by an offset and length.
/// # Implementation
/// This operation is `O(1)` as it amounts to increase two ref counts.
/// # Safety
/// The caller must ensure that `offset + length <= self.len()`.
#[inline]
#[must_use]
pub unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Self {
let validity = self
.validity
.clone()
.map(|bitmap| bitmap.slice_unchecked(offset, length))
.and_then(|bitmap| (bitmap.unset_bits() > 0).then(|| bitmap));
Self {
data_type: self.data_type.clone(),
values: self.values.clone().slice_unchecked(offset, length),
validity,
}
}
/// Returns this [`PrimitiveArray`] with a new validity.
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
#[must_use]
pub fn with_validity(mut self, validity: Option<Bitmap>) -> Self {
self.set_validity(validity);
self
}
/// Sets the validity of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
pub fn set_validity(&mut self, validity: Option<Bitmap>) {
if matches!(&validity, Some(bitmap) if bitmap.len() != self.len()) {
panic!("validity's length must be equal to the array's length")
}
self.validity = validity;
}
/// Returns this [`PrimitiveArray`] with new values.
/// # Panics
/// This function panics iff `values.len() != self.len()`.
#[must_use]
pub fn with_values(mut self, values: Buffer<T>) -> Self {
self.set_values(values);
self
}
/// Update the values of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `values.len() != self.len()`.
pub fn set_values(&mut self, values: Buffer<T>) {
assert_eq!(
values.len(),
self.len(),
"values' length must be equal to this arrays' length"
);
self.values = values;
}
104 105 106 107 108 109 110 111 112 113 114 115
fn binary_scalar<T: NativeType, F: Fn(&PrimitiveArray<T>, &T) -> PrimitiveArray<T>>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveScalar<T>,
op: F,
) -> PrimitiveArray<T> {
let rhs = if let Some(rhs) = *rhs.value() {
rhs
} else {
return PrimitiveArray::<T>::new_null(lhs.data_type().clone(), lhs.len());
};
op(lhs, &rhs)
}
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
pub fn sum_primitive<T>(array: &PrimitiveArray<T>) -> Option<T>
where
T: NativeType + Simd + Add<Output = T> + std::iter::Sum<T>,
T::Simd: Add<Output = T::Simd> + Sum<T>,
{
let null_count = array.null_count();
if null_count == array.len() {
return None;
}
match array.validity() {
None => Some(nonnull_sum(array.values())),
Some(bitmap) => Some(null_sum(array.values(), bitmap)),
}
}
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
pub fn min_primitive<T>(array: &PrimitiveArray<T>) -> Option<T>
where
T: NativeType + Simd,
T::Simd: SimdOrd<T>,
{
let null_count = array.null_count();
// Includes case array.len() == 0
if null_count == array.len() {
return None;
}
let values = array.values();
Some(if let Some(validity) = array.validity() {
null_min_primitive(values, validity)
} else {
nonnull_min_primitive(values)
})
}
/// Returns the maximum value in the array, according to the natural order.
/// For floating point arrays any NaN values are considered to be greater than any other non-null value
pub fn max_primitive<T>(array: &PrimitiveArray<T>) -> Option<T>
where
T: NativeType + Simd,
T::Simd: SimdOrd<T>,
{
let null_count = array.null_count();
// Includes case array.len() == 0
if null_count == array.len() {
return None;
}
let values = array.values();
Some(if let Some(validity) = array.validity() {
null_max_primitive(values, validity)
} else {
nonnull_max_primitive(values)
})
}
- src/io/ipc/write/serialize.rs
- src/compute/sort/primitive/indices.rs
- src/compute/filter.rs
- src/compute/arity.rs
- src/array/dictionary/mod.rs
- src/compute/arithmetics/time.rs
- src/compute/take/boolean.rs
- src/compute/take/primitive.rs
- src/compute/sort/primitive/sort.rs
- src/io/parquet/write/primitive/basic.rs
- src/compute/take/generic_binary.rs
- src/compute/take/list.rs
- src/compute/cast/primitive_to.rs
- src/compute/contains.rs
- src/compute/arithmetics/decimal/div.rs
- src/io/json_integration/write/array.rs
- src/compute/arithmetics/decimal/mul.rs
- src/compute/take/mod.rs
- src/io/parquet/write/mod.rs
sourcepub fn values(&self) -> &Buffer<T>
pub fn values(&self) -> &Buffer<T>
The values Buffer
.
Values on null slots are undetermined (they can be anything).
Examples found in repository?
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
fn primitive<T: NativeType>(array: &PrimitiveArray<T>, values: &mut [T]) {
values.copy_from_slice(array.values())
}
fn write_validity(validity: Option<&Bitmap>, indicators: &mut [isize]) {
if let Some(validity) = validity {
indicators
.iter_mut()
.zip(validity.iter())
.for_each(|(indicator, is_valid)| *indicator = if is_valid { 0 } else { -1 })
} else {
indicators.iter_mut().for_each(|x| *x = 0)
}
}
fn primitive_optional<T: NativeType>(array: &PrimitiveArray<T>, values: &mut NullableSliceMut<T>) {
let (values, indicators) = values.raw_values();
values.copy_from_slice(array.values());
write_validity(array.validity(), indicators);
}
More examples
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
pub fn iter(&self) -> ZipValidity<&T, std::slice::Iter<T>, BitmapIter> {
ZipValidity::new_with_validity(self.values().iter(), self.validity())
}
/// Returns an iterator of the values, `&T`, ignoring the arrays' validity.
#[inline]
pub fn values_iter(&self) -> std::slice::Iter<T> {
self.values().iter()
}
/// Returns the length of this array
#[inline]
pub fn len(&self) -> usize {
self.values.len()
}
/// The values [`Buffer`].
/// Values on null slots are undetermined (they can be anything).
#[inline]
pub fn values(&self) -> &Buffer<T> {
&self.values
}
/// Returns the optional validity.
#[inline]
pub fn validity(&self) -> Option<&Bitmap> {
self.validity.as_ref()
}
/// Returns the arrays' [`DataType`].
#[inline]
pub fn data_type(&self) -> &DataType {
&self.data_type
}
/// Returns the value at slot `i`.
///
/// Equivalent to `self.values()[i]`. The value of a null slot is undetermined (it can be anything).
/// # Panic
/// This function panics iff `i >= self.len`.
#[inline]
pub fn value(&self, i: usize) -> T {
self.values()[i]
}
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
pub fn unary<I, F, O>(array: &PrimitiveArray<I>, op: F, data_type: DataType) -> PrimitiveArray<O>
where
I: NativeType,
O: NativeType,
F: Fn(I) -> O,
{
let values = array.values().iter().map(|v| op(*v)).collect::<Vec<_>>();
PrimitiveArray::<O>::new(data_type, values.into(), array.validity().cloned())
}
/// Version of unary that checks for errors in the closure used to create the
/// buffer
pub fn try_unary<I, F, O>(
array: &PrimitiveArray<I>,
op: F,
data_type: DataType,
) -> Result<PrimitiveArray<O>>
where
I: NativeType,
O: NativeType,
F: Fn(I) -> Result<O>,
{
let values = array
.values()
.iter()
.map(|v| op(*v))
.collect::<Result<Vec<_>>>()?
.into();
Ok(PrimitiveArray::<O>::new(
data_type,
values,
array.validity().cloned(),
))
}
/// Version of unary that returns an array and bitmap. Used when working with
/// overflowing operations
pub fn unary_with_bitmap<I, F, O>(
array: &PrimitiveArray<I>,
op: F,
data_type: DataType,
) -> (PrimitiveArray<O>, Bitmap)
where
I: NativeType,
O: NativeType,
F: Fn(I) -> (O, bool),
{
let mut mut_bitmap = MutableBitmap::with_capacity(array.len());
let values = array
.values()
.iter()
.map(|v| {
let (res, over) = op(*v);
mut_bitmap.push(over);
res
})
.collect::<Vec<_>>()
.into();
(
PrimitiveArray::<O>::new(data_type, values, array.validity().cloned()),
mut_bitmap.into(),
)
}
/// Version of unary that creates a mutable bitmap that is used to keep track
/// of checked operations. The resulting bitmap is compared with the array
/// bitmap to create the final validity array.
pub fn unary_checked<I, F, O>(
array: &PrimitiveArray<I>,
op: F,
data_type: DataType,
) -> PrimitiveArray<O>
where
I: NativeType,
O: NativeType,
F: Fn(I) -> Option<O>,
{
let mut mut_bitmap = MutableBitmap::with_capacity(array.len());
let values = array
.values()
.iter()
.map(|v| match op(*v) {
Some(val) => {
mut_bitmap.push(true);
val
}
None => {
mut_bitmap.push(false);
O::default()
}
})
.collect::<Vec<_>>()
.into();
// The validity has to be checked against the bitmap created during the
// creation of the values with the iterator. If an error was found during
// the iteration, then the validity is changed to None to mark the value
// as Null
let bitmap: Bitmap = mut_bitmap.into();
let validity = combine_validities(array.validity(), Some(&bitmap));
PrimitiveArray::<O>::new(data_type, values, validity)
}
/// Applies a binary operations to two primitive arrays. This is the fastest
/// way to perform an operation on two primitive array when the benefits of a
/// vectorized operation outweighs the cost of branching nulls and non-nulls.
/// # Errors
/// This function errors iff the arrays have a different length.
/// # Implementation
/// This will apply the function for all values, including those on null slots.
/// This implies that the operation must be infallible for any value of the
/// corresponding type.
/// The types of the arrays are not checked with this operation. The closure
/// "op" needs to handle the different types in the arrays. The datatype for the
/// resulting array has to be selected by the implementer of the function as
/// an argument for the function.
#[inline]
pub fn binary<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> PrimitiveArray<T>
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> T,
{
check_same_len(lhs, rhs).unwrap();
let validity = combine_validities(lhs.validity(), rhs.validity());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Vec<_>>()
.into();
PrimitiveArray::<T>::new(data_type, values, validity)
}
/// Version of binary that checks for errors in the closure used to create the
/// buffer
pub fn try_binary<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> Result<PrimitiveArray<T>>
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> Result<T>,
{
check_same_len(lhs, rhs)?;
let validity = combine_validities(lhs.validity(), rhs.validity());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Result<Vec<_>>>()?
.into();
Ok(PrimitiveArray::<T>::new(data_type, values, validity))
}
/// Version of binary that returns an array and bitmap. Used when working with
/// overflowing operations
pub fn binary_with_bitmap<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> (T, bool),
{
check_same_len(lhs, rhs).unwrap();
let validity = combine_validities(lhs.validity(), rhs.validity());
let mut mut_bitmap = MutableBitmap::with_capacity(lhs.len());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| {
let (res, over) = op(*l, *r);
mut_bitmap.push(over);
res
})
.collect::<Vec<_>>()
.into();
(
PrimitiveArray::<T>::new(data_type, values, validity),
mut_bitmap.into(),
)
}
/// Version of binary that creates a mutable bitmap that is used to keep track
/// of checked operations. The resulting bitmap is compared with the array
/// bitmap to create the final validity array.
pub fn binary_checked<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> PrimitiveArray<T>
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> Option<T>,
{
check_same_len(lhs, rhs).unwrap();
let mut mut_bitmap = MutableBitmap::with_capacity(lhs.len());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| match op(*l, *r) {
Some(val) => {
mut_bitmap.push(true);
val
}
None => {
mut_bitmap.push(false);
T::default()
}
})
.collect::<Vec<_>>()
.into();
let bitmap: Bitmap = mut_bitmap.into();
let validity = combine_validities(lhs.validity(), rhs.validity());
// The validity has to be checked against the bitmap created during the
// creation of the values with the iterator. If an error was found during
// the iteration, then the validity is changed to None to mark the value
// as Null
let validity = combine_validities(validity.as_ref(), Some(&bitmap));
PrimitiveArray::<T>::new(data_type, values, validity)
}
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
fn compare_op<T, F>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>, op: F) -> BooleanArray
where
T: NativeType + Simd8,
F: Fn(T::Simd, T::Simd) -> u8,
{
let validity = combine_validities(lhs.validity(), rhs.validity());
let values = compare_values_op(lhs.values(), rhs.values(), op);
BooleanArray::new(DataType::Boolean, values.into(), validity)
}
/// Evaluate `op(left, right)` for [`PrimitiveArray`] and scalar using
/// a specified comparison function.
pub fn compare_op_scalar<T, F>(lhs: &PrimitiveArray<T>, rhs: T, op: F) -> BooleanArray
where
T: NativeType + Simd8,
F: Fn(T::Simd, T::Simd) -> u8,
{
let validity = lhs.validity().cloned();
let values = compare_values_op_scalar(lhs.values(), rhs, op);
BooleanArray::new(DataType::Boolean, values.into(), validity)
}
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
pub fn unary<I, F>(array: &mut PrimitiveArray<I>, op: F)
where
I: NativeType,
F: Fn(I) -> I,
{
if let Some(values) = array.get_mut_values() {
// mutate in place
values.iter_mut().for_each(|l| *l = op(*l));
} else {
// alloc and write to new region
let values = array.values().iter().map(|l| op(*l)).collect::<Vec<_>>();
array.set_values(values.into());
}
}
/// Applies a binary function to two [`PrimitiveArray`]s, optionally in-place, returning
/// a new [`PrimitiveArray`].
///
/// # Implementation
/// This function tries to apply the function directly to the values of the array.
/// If that region is shared, this function creates a new region and writes to it.
/// # Panics
/// This function panics iff
/// * the arrays have a different length.
/// * the function itself panics.
#[inline]
pub fn binary<T, D, F>(lhs: &mut PrimitiveArray<T>, rhs: &PrimitiveArray<D>, op: F)
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> T,
{
check_same_len(lhs, rhs).unwrap();
// both for the validity and for the values
// we branch to check if we can mutate in place
// if we can, great that is fastest.
// if we cannot, we allocate a new buffer and assign values to that
// new buffer, that is benchmarked to be ~2x faster than first memcpy and assign in place
// for the validity bits it can be much faster as we might need to iterate all bits if the
// bitmap has an offset.
if let Some(rhs) = rhs.validity() {
if lhs.validity().is_none() {
lhs.set_validity(Some(rhs.clone()));
} else {
lhs.apply_validity(|bitmap| {
match bitmap.into_mut() {
Either::Left(immutable) => {
// alloc new region
&immutable & rhs
}
Either::Right(mutable) => {
// mutate in place
(mutable & rhs).into()
}
}
});
}
};
if let Some(values) = lhs.get_mut_values() {
// mutate values in place
values
.iter_mut()
.zip(rhs.values().iter())
.for_each(|(l, r)| *l = op(*l, *r));
} else {
// alloc new region
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Vec<_>>();
lhs.set_values(values.into());
}
}
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
pub fn sum_primitive<T>(array: &PrimitiveArray<T>) -> Option<T>
where
T: NativeType + Simd + Add<Output = T> + std::iter::Sum<T>,
T::Simd: Add<Output = T::Simd> + Sum<T>,
{
let null_count = array.null_count();
if null_count == array.len() {
return None;
}
match array.validity() {
None => Some(nonnull_sum(array.values())),
Some(bitmap) => Some(null_sum(array.values(), bitmap)),
}
}
- src/compute/aggregate/min_max.rs
- src/compute/nullif.rs
- src/io/ipc/write/serialize.rs
- src/compute/sort/primitive/indices.rs
- src/compute/filter.rs
- src/compute/take/primitive.rs
- src/compute/cast/decimal_to.rs
- src/array/ord.rs
- src/compute/take/boolean.rs
- src/array/dictionary/mod.rs
- src/compute/take/binary.rs
- src/compute/take/utf8.rs
- src/compute/sort/primitive/sort.rs
- src/io/parquet/write/primitive/basic.rs
- src/compute/take/structure.rs
- src/array/growable/primitive.rs
- src/compute/take/generic_binary.rs
- src/compute/take/list.rs
- src/compute/cast/primitive_to.rs
- src/array/growable/dictionary.rs
- src/compute/arithmetics/decimal/add.rs
- src/compute/arithmetics/decimal/sub.rs
- src/compute/arithmetics/decimal/mul.rs
- src/compute/arithmetics/decimal/div.rs
- src/io/parquet/write/mod.rs
- src/io/avro/write/serialize.rs
sourcepub fn validity(&self) -> Option<&Bitmap>
pub fn validity(&self) -> Option<&Bitmap>
Returns the optional validity.
Examples found in repository?
More examples
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
pub fn iter(&self) -> ZipValidity<Box<dyn Scalar>, DictionaryValuesIter<K>, BitmapIter> {
ZipValidity::new_with_validity(DictionaryValuesIter::new(self), self.keys.validity())
}
/// Returns an iterator of [`Box<dyn Scalar>`]
/// # Implementation
/// This function will allocate a new [`Scalar`] per item and is usually not performant.
/// Consider calling `keys_iter` and `values`, downcasting `values`, and iterating over that.
pub fn values_iter(&self) -> DictionaryValuesIter<K> {
DictionaryValuesIter::new(self)
}
/// Returns the [`DataType`] of this [`DictionaryArray`]
#[inline]
pub fn data_type(&self) -> &DataType {
&self.data_type
}
/// Returns whether the values of this [`DictionaryArray`] are ordered
#[inline]
pub fn is_ordered(&self) -> bool {
match self.data_type.to_logical_type() {
DataType::Dictionary(_, _, is_ordered) => *is_ordered,
_ => unreachable!(),
}
}
pub(crate) fn default_data_type(values_datatype: DataType) -> DataType {
DataType::Dictionary(K::KEY_TYPE, Box::new(values_datatype), false)
}
/// Creates a new [`DictionaryArray`] by slicing the existing [`DictionaryArray`].
/// # Panics
/// iff `offset + length > self.len()`.
pub fn slice(&self, offset: usize, length: usize) -> Self {
Self {
data_type: self.data_type.clone(),
keys: self.keys.clone().slice(offset, length),
values: self.values.clone(),
}
}
/// Creates a new [`DictionaryArray`] by slicing the existing [`DictionaryArray`].
/// # Safety
/// Safe iff `offset + length <= self.len()`.
pub unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Self {
Self {
data_type: self.data_type.clone(),
keys: self.keys.clone().slice_unchecked(offset, length),
values: self.values.clone(),
}
}
/// Returns this [`DictionaryArray`] with a new validity.
/// # Panic
/// This function panics iff `validity.len() != self.len()`.
#[must_use]
pub fn with_validity(mut self, validity: Option<Bitmap>) -> Self {
self.set_validity(validity);
self
}
/// Sets the validity of the keys of this [`DictionaryArray`].
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
pub fn set_validity(&mut self, validity: Option<Bitmap>) {
self.keys.set_validity(validity);
}
/// Returns the length of this array
#[inline]
pub fn len(&self) -> usize {
self.keys.len()
}
/// The optional validity. Equivalent to `self.keys().validity()`.
#[inline]
pub fn validity(&self) -> Option<&Bitmap> {
self.keys.validity()
}
/// Returns the keys of the [`DictionaryArray`]. These keys can be used to fetch values
/// from `values`.
#[inline]
pub fn keys(&self) -> &PrimitiveArray<K> {
&self.keys
}
/// Returns an iterator of the keys' values of the [`DictionaryArray`] as `usize`
#[inline]
pub fn keys_values_iter(&self) -> impl TrustedLen<Item = usize> + Clone + '_ {
// safety - invariant of the struct
self.keys.values_iter().map(|x| unsafe { x.as_usize() })
}
/// Returns an iterator of the keys' of the [`DictionaryArray`] as `usize`
#[inline]
pub fn keys_iter(&self) -> impl TrustedLen<Item = Option<usize>> + Clone + '_ {
// safety - invariant of the struct
self.keys.iter().map(|x| x.map(|x| unsafe { x.as_usize() }))
}
/// Returns the keys' value of the [`DictionaryArray`] as `usize`
/// # Panics
/// This function panics iff `index >= self.len()`
#[inline]
pub fn key_value(&self, index: usize) -> usize {
// safety - invariant of the struct
unsafe { self.keys.values()[index].as_usize() }
}
/// Returns the values of the [`DictionaryArray`].
#[inline]
pub fn values(&self) -> &Box<dyn Array> {
&self.values
}
/// Returns the value of the [`DictionaryArray`] at position `i`.
/// # Implementation
/// This function will allocate a new [`Scalar`] and is usually not performant.
/// Consider calling `keys` and `values`, downcasting `values`, and iterating over that.
/// # Panic
/// This function panics iff `index >= self.len()`
#[inline]
pub fn value(&self, index: usize) -> Box<dyn Scalar> {
// safety - invariant of this struct
let index = unsafe { self.keys.value(index).as_usize() };
new_scalar(self.values.as_ref(), index)
}
/// Boxes self into a [`Box<dyn Array>`].
pub fn boxed(self) -> Box<dyn Array> {
Box::new(self)
}
/// Boxes self into a [`std::sync::Arc<dyn Array>`].
pub fn arced(self) -> std::sync::Arc<dyn Array> {
std::sync::Arc::new(self)
}
pub(crate) fn try_get_child(data_type: &DataType) -> Result<&DataType, Error> {
Ok(match data_type.to_logical_type() {
DataType::Dictionary(_, values, _) => values.as_ref(),
_ => {
return Err(Error::oos(
"Dictionaries must be initialized with DataType::Dictionary",
))
}
})
}
}
impl<K: DictionaryKey> Array for DictionaryArray<K> {
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn len(&self) -> usize {
self.len()
}
#[inline]
fn data_type(&self) -> &DataType {
&self.data_type
}
fn validity(&self) -> Option<&Bitmap> {
self.keys.validity()
}
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
pub fn unary<I, F, O>(array: &PrimitiveArray<I>, op: F, data_type: DataType) -> PrimitiveArray<O>
where
I: NativeType,
O: NativeType,
F: Fn(I) -> O,
{
let values = array.values().iter().map(|v| op(*v)).collect::<Vec<_>>();
PrimitiveArray::<O>::new(data_type, values.into(), array.validity().cloned())
}
/// Version of unary that checks for errors in the closure used to create the
/// buffer
pub fn try_unary<I, F, O>(
array: &PrimitiveArray<I>,
op: F,
data_type: DataType,
) -> Result<PrimitiveArray<O>>
where
I: NativeType,
O: NativeType,
F: Fn(I) -> Result<O>,
{
let values = array
.values()
.iter()
.map(|v| op(*v))
.collect::<Result<Vec<_>>>()?
.into();
Ok(PrimitiveArray::<O>::new(
data_type,
values,
array.validity().cloned(),
))
}
/// Version of unary that returns an array and bitmap. Used when working with
/// overflowing operations
pub fn unary_with_bitmap<I, F, O>(
array: &PrimitiveArray<I>,
op: F,
data_type: DataType,
) -> (PrimitiveArray<O>, Bitmap)
where
I: NativeType,
O: NativeType,
F: Fn(I) -> (O, bool),
{
let mut mut_bitmap = MutableBitmap::with_capacity(array.len());
let values = array
.values()
.iter()
.map(|v| {
let (res, over) = op(*v);
mut_bitmap.push(over);
res
})
.collect::<Vec<_>>()
.into();
(
PrimitiveArray::<O>::new(data_type, values, array.validity().cloned()),
mut_bitmap.into(),
)
}
/// Version of unary that creates a mutable bitmap that is used to keep track
/// of checked operations. The resulting bitmap is compared with the array
/// bitmap to create the final validity array.
pub fn unary_checked<I, F, O>(
array: &PrimitiveArray<I>,
op: F,
data_type: DataType,
) -> PrimitiveArray<O>
where
I: NativeType,
O: NativeType,
F: Fn(I) -> Option<O>,
{
let mut mut_bitmap = MutableBitmap::with_capacity(array.len());
let values = array
.values()
.iter()
.map(|v| match op(*v) {
Some(val) => {
mut_bitmap.push(true);
val
}
None => {
mut_bitmap.push(false);
O::default()
}
})
.collect::<Vec<_>>()
.into();
// The validity has to be checked against the bitmap created during the
// creation of the values with the iterator. If an error was found during
// the iteration, then the validity is changed to None to mark the value
// as Null
let bitmap: Bitmap = mut_bitmap.into();
let validity = combine_validities(array.validity(), Some(&bitmap));
PrimitiveArray::<O>::new(data_type, values, validity)
}
/// Applies a binary operations to two primitive arrays. This is the fastest
/// way to perform an operation on two primitive array when the benefits of a
/// vectorized operation outweighs the cost of branching nulls and non-nulls.
/// # Errors
/// This function errors iff the arrays have a different length.
/// # Implementation
/// This will apply the function for all values, including those on null slots.
/// This implies that the operation must be infallible for any value of the
/// corresponding type.
/// The types of the arrays are not checked with this operation. The closure
/// "op" needs to handle the different types in the arrays. The datatype for the
/// resulting array has to be selected by the implementer of the function as
/// an argument for the function.
#[inline]
pub fn binary<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> PrimitiveArray<T>
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> T,
{
check_same_len(lhs, rhs).unwrap();
let validity = combine_validities(lhs.validity(), rhs.validity());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Vec<_>>()
.into();
PrimitiveArray::<T>::new(data_type, values, validity)
}
/// Version of binary that checks for errors in the closure used to create the
/// buffer
pub fn try_binary<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> Result<PrimitiveArray<T>>
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> Result<T>,
{
check_same_len(lhs, rhs)?;
let validity = combine_validities(lhs.validity(), rhs.validity());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Result<Vec<_>>>()?
.into();
Ok(PrimitiveArray::<T>::new(data_type, values, validity))
}
/// Version of binary that returns an array and bitmap. Used when working with
/// overflowing operations
pub fn binary_with_bitmap<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> (T, bool),
{
check_same_len(lhs, rhs).unwrap();
let validity = combine_validities(lhs.validity(), rhs.validity());
let mut mut_bitmap = MutableBitmap::with_capacity(lhs.len());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| {
let (res, over) = op(*l, *r);
mut_bitmap.push(over);
res
})
.collect::<Vec<_>>()
.into();
(
PrimitiveArray::<T>::new(data_type, values, validity),
mut_bitmap.into(),
)
}
/// Version of binary that creates a mutable bitmap that is used to keep track
/// of checked operations. The resulting bitmap is compared with the array
/// bitmap to create the final validity array.
pub fn binary_checked<T, D, F>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<D>,
data_type: DataType,
op: F,
) -> PrimitiveArray<T>
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> Option<T>,
{
check_same_len(lhs, rhs).unwrap();
let mut mut_bitmap = MutableBitmap::with_capacity(lhs.len());
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| match op(*l, *r) {
Some(val) => {
mut_bitmap.push(true);
val
}
None => {
mut_bitmap.push(false);
T::default()
}
})
.collect::<Vec<_>>()
.into();
let bitmap: Bitmap = mut_bitmap.into();
let validity = combine_validities(lhs.validity(), rhs.validity());
// The validity has to be checked against the bitmap created during the
// creation of the values with the iterator. If an error was found during
// the iteration, then the validity is changed to None to mark the value
// as Null
let validity = combine_validities(validity.as_ref(), Some(&bitmap));
PrimitiveArray::<T>::new(data_type, values, validity)
}
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
fn compare_op<T, F>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>, op: F) -> BooleanArray
where
T: NativeType + Simd8,
F: Fn(T::Simd, T::Simd) -> u8,
{
let validity = combine_validities(lhs.validity(), rhs.validity());
let values = compare_values_op(lhs.values(), rhs.values(), op);
BooleanArray::new(DataType::Boolean, values.into(), validity)
}
/// Evaluate `op(left, right)` for [`PrimitiveArray`] and scalar using
/// a specified comparison function.
pub fn compare_op_scalar<T, F>(lhs: &PrimitiveArray<T>, rhs: T, op: F) -> BooleanArray
where
T: NativeType + Simd8,
F: Fn(T::Simd, T::Simd) -> u8,
{
let validity = lhs.validity().cloned();
let values = compare_values_op_scalar(lhs.values(), rhs, op);
BooleanArray::new(DataType::Boolean, values.into(), validity)
}
/// Perform `lhs == rhs` operation on two arrays.
pub fn eq<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
compare_op(lhs, rhs, |a, b| a.eq(b))
}
/// Perform `lhs == rhs` operation on two arrays and include validities in comparison.
pub fn eq_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity_lhs = lhs.validity().cloned();
let validity_rhs = rhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let rhs = rhs.clone().with_validity(None);
let out = compare_op(&lhs, &rhs, |a, b| a.eq(b));
finish_eq_validities(out, validity_lhs, validity_rhs)
}
/// Perform `left == right` operation on an array and a scalar value.
pub fn eq_scalar<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
compare_op_scalar(lhs, rhs, |a, b| a.eq(b))
}
/// Perform `left == right` operation on an array and a scalar value and include validities in comparison.
pub fn eq_scalar_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity = lhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let out = compare_op_scalar(&lhs, rhs, |a, b| a.eq(b));
finish_eq_validities(out, validity, None)
}
/// Perform `left != right` operation on two arrays.
pub fn neq<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
compare_op(lhs, rhs, |a, b| a.neq(b))
}
/// Perform `left != right` operation on two arrays and include validities in comparison.
pub fn neq_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity_lhs = lhs.validity().cloned();
let validity_rhs = rhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let rhs = rhs.clone().with_validity(None);
let out = compare_op(&lhs, &rhs, |a, b| a.neq(b));
finish_neq_validities(out, validity_lhs, validity_rhs)
}
/// Perform `left != right` operation on an array and a scalar value.
pub fn neq_scalar<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
compare_op_scalar(lhs, rhs, |a, b| a.neq(b))
}
/// Perform `left != right` operation on an array and a scalar value and include validities in comparison.
pub fn neq_scalar_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity = lhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let out = compare_op_scalar(&lhs, rhs, |a, b| a.neq(b));
finish_neq_validities(out, validity, None)
}
- src/compute/aggregate/sum.rs
- src/compute/aggregate/min_max.rs
- src/compute/nullif.rs
- src/io/ipc/write/serialize.rs
- src/compute/sort/primitive/indices.rs
- src/io/parquet/write/dictionary.rs
- src/compute/filter.rs
- src/compute/take/primitive.rs
- src/compute/cast/decimal_to.rs
- src/compute/take/boolean.rs
- src/compute/sort/primitive/sort.rs
- src/compute/take/structure.rs
- src/compute/take/generic_binary.rs
- src/compute/take/list.rs
- src/compute/cast/primitive_to.rs
- src/compute/contains.rs
- src/io/parquet/write/primitive/basic.rs
- src/compute/arity_assign.rs
- src/compute/arithmetics/decimal/add.rs
- src/compute/arithmetics/decimal/sub.rs
- src/compute/arithmetics/decimal/mul.rs
- src/compute/arithmetics/decimal/div.rs
- src/io/parquet/write/mod.rs
sourcepub fn data_type(&self) -> &DataType
pub fn data_type(&self) -> &DataType
Returns the arrays’ DataType
.
Examples found in repository?
More examples
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
pub fn negate<T>(array: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeType + Neg<Output = T>,
{
unary(array, |a| -a, array.data_type().clone())
}
/// Checked negates values from array.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::checked_negate;
/// use arrow2::array::{Array, PrimitiveArray};
///
/// let a = PrimitiveArray::from([None, Some(6), Some(i8::MIN), Some(7)]);
/// let result = checked_negate(&a);
/// let expected = PrimitiveArray::from([None, Some(-6), None, Some(-7)]);
/// assert_eq!(result, expected);
/// assert!(!result.is_valid(2))
/// ```
pub fn checked_negate<T>(array: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeType + CheckedNeg,
{
unary_checked(array, |a| a.checked_neg(), array.data_type().clone())
}
/// Wrapping negates values from array.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::wrapping_negate;
/// use arrow2::array::{Array, PrimitiveArray};
///
/// let a = PrimitiveArray::from([None, Some(6), Some(i8::MIN), Some(7)]);
/// let result = wrapping_negate(&a);
/// let expected = PrimitiveArray::from([None, Some(-6), Some(i8::MIN), Some(-7)]);
/// assert_eq!(result, expected);
/// ```
pub fn wrapping_negate<T>(array: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeType + WrappingNeg,
{
unary(array, |a| a.wrapping_neg(), array.data_type().clone())
}
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
pub fn or<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeType + BitOr<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a | b)
}
/// Performs `XOR` operation between two [`PrimitiveArray`]s.
/// # Panic
/// This function errors when the arrays have different lengths.
pub fn xor<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeType + BitXor<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a ^ b)
}
/// Performs `AND` operation on two [`PrimitiveArray`]s.
/// # Panic
/// This function panics when the arrays have different lengths.
pub fn and<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeType + BitAnd<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a & b)
}
/// Returns a new [`PrimitiveArray`] with the bitwise `not`.
pub fn not<T>(array: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeType + Not<Output = T>,
{
let op = move |a: T| !a;
unary(array, op, array.data_type().clone())
}
/// Performs `OR` operation between a [`PrimitiveArray`] and scalar.
/// # Panic
/// This function errors when the arrays have different lengths.
pub fn or_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + BitOr<Output = T>,
{
unary(lhs, |a| a | *rhs, lhs.data_type().clone())
}
/// Performs `XOR` operation between a [`PrimitiveArray`] and scalar.
/// # Panic
/// This function errors when the arrays have different lengths.
pub fn xor_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + BitXor<Output = T>,
{
unary(lhs, |a| a ^ *rhs, lhs.data_type().clone())
}
/// Performs `AND` operation between a [`PrimitiveArray`] and scalar.
/// # Panic
/// This function panics when the arrays have different lengths.
pub fn and_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + BitAnd<Output = T>,
{
unary(lhs, |a| a & *rhs, lhs.data_type().clone())
}
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
pub fn add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + Add<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a + b)
}
/// Wrapping addition of two [`PrimitiveArray`]s.
/// It wraps around at the boundary of the type if the result overflows.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::wrapping_add;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([Some(-100i8), Some(100i8), Some(100i8)]);
/// let b = PrimitiveArray::from([Some(0i8), Some(100i8), Some(0i8)]);
/// let result = wrapping_add(&a, &b);
/// let expected = PrimitiveArray::from([Some(-100i8), Some(-56i8), Some(100i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn wrapping_add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingAdd<Output = T>,
{
let op = move |a: T, b: T| a.wrapping_add(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
/// Checked addition of two primitive arrays. If the result from the sum
/// overflows, the validity for that index is changed to None
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::checked_add;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([Some(100i8), Some(100i8), Some(100i8)]);
/// let b = PrimitiveArray::from([Some(0i8), Some(100i8), Some(0i8)]);
/// let result = checked_add(&a, &b);
/// let expected = PrimitiveArray::from([Some(100i8), None, Some(100i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn checked_add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedAdd<Output = T>,
{
let op = move |a: T, b: T| a.checked_add(&b);
binary_checked(lhs, rhs, lhs.data_type().clone(), op)
}
/// Saturating addition of two primitive arrays. If the result from the sum is
/// larger than the possible number for this type, the result for the operation
/// will be the saturated value.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::saturating_add;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([Some(100i8)]);
/// let b = PrimitiveArray::from([Some(100i8)]);
/// let result = saturating_add(&a, &b);
/// let expected = PrimitiveArray::from([Some(127)]);
/// assert_eq!(result, expected);
/// ```
pub fn saturating_add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingAdd<Output = T>,
{
let op = move |a: T, b: T| a.saturating_add(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
/// Overflowing addition of two primitive arrays. If the result from the sum is
/// larger than the possible number for this type, the result for the operation
/// will be an array with overflowed values and a validity array indicating
/// the overflowing elements from the array.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::overflowing_add;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([Some(1i8), Some(100i8)]);
/// let b = PrimitiveArray::from([Some(1i8), Some(100i8)]);
/// let (result, overflow) = overflowing_add(&a, &b);
/// let expected = PrimitiveArray::from([Some(2i8), Some(-56i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn overflowing_add<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingAdd<Output = T>,
{
let op = move |a: T, b: T| a.overflowing_add(&b);
binary_with_bitmap(lhs, rhs, lhs.data_type().clone(), op)
}
// Implementation of ArrayAdd trait for PrimitiveArrays
impl<T> ArrayAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + Add<Output = T>,
{
fn add(&self, rhs: &PrimitiveArray<T>) -> Self {
add(self, rhs)
}
}
impl<T> ArrayWrappingAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + WrappingAdd<Output = T>,
{
fn wrapping_add(&self, rhs: &PrimitiveArray<T>) -> Self {
wrapping_add(self, rhs)
}
}
// Implementation of ArrayCheckedAdd trait for PrimitiveArrays
impl<T> ArrayCheckedAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedAdd<Output = T>,
{
fn checked_add(&self, rhs: &PrimitiveArray<T>) -> Self {
checked_add(self, rhs)
}
}
// Implementation of ArraySaturatingAdd trait for PrimitiveArrays
impl<T> ArraySaturatingAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingAdd<Output = T>,
{
fn saturating_add(&self, rhs: &PrimitiveArray<T>) -> Self {
saturating_add(self, rhs)
}
}
// Implementation of ArraySaturatingAdd trait for PrimitiveArrays
impl<T> ArrayOverflowingAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingAdd<Output = T>,
{
fn overflowing_add(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap) {
overflowing_add(self, rhs)
}
}
/// Adds a scalar T to a primitive array of type T.
/// Panics if the sum of the values overflows.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::add_scalar;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([None, Some(6), None, Some(6)]);
/// let result = add_scalar(&a, &1i32);
/// let expected = PrimitiveArray::from([None, Some(7), None, Some(7)]);
/// assert_eq!(result, expected)
/// ```
pub fn add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + Add<Output = T>,
{
let rhs = *rhs;
unary(lhs, |a| a + rhs, lhs.data_type().clone())
}
/// Wrapping addition of a scalar T to a [`PrimitiveArray`] of type T.
/// It do nothing if the result overflows.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::wrapping_add_scalar;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[None, Some(100)]);
/// let result = wrapping_add_scalar(&a, &100i8);
/// let expected = Int8Array::from(&[None, Some(-56)]);
/// assert_eq!(result, expected);
/// ```
pub fn wrapping_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingAdd<Output = T>,
{
unary(lhs, |a| a.wrapping_add(rhs), lhs.data_type().clone())
}
/// Checked addition of a scalar T to a primitive array of type T. If the
/// result from the sum overflows then the validity index for that value is
/// changed to None
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::checked_add_scalar;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[None, Some(100), None, Some(100)]);
/// let result = checked_add_scalar(&a, &100i8);
/// let expected = Int8Array::from(&[None, None, None, None]);
/// assert_eq!(result, expected);
/// ```
pub fn checked_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedAdd<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.checked_add(&rhs);
unary_checked(lhs, op, lhs.data_type().clone())
}
/// Saturated addition of a scalar T to a primitive array of type T. If the
/// result from the sum is larger than the possible number for this type, then
/// the result will be saturated
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::saturating_add_scalar;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([Some(100i8)]);
/// let result = saturating_add_scalar(&a, &100i8);
/// let expected = PrimitiveArray::from([Some(127)]);
/// assert_eq!(result, expected);
/// ```
pub fn saturating_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingAdd<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.saturating_add(&rhs);
unary(lhs, op, lhs.data_type().clone())
}
/// Overflowing addition of a scalar T to a primitive array of type T. If the
/// result from the sum is larger than the possible number for this type, then
/// the result will be an array with overflowed values and a validity array
/// indicating the overflowing elements from the array
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::overflowing_add_scalar;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([Some(1i8), Some(100i8)]);
/// let (result, overflow) = overflowing_add_scalar(&a, &100i8);
/// let expected = PrimitiveArray::from([Some(101i8), Some(-56i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn overflowing_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingAdd<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.overflowing_add(&rhs);
unary_with_bitmap(lhs, op, lhs.data_type().clone())
}
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
pub fn mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + Mul<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a * b)
}
/// Wrapping multiplication of two [`PrimitiveArray`]s.
/// It wraps around at the boundary of the type if the result overflows.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::wrapping_mul;
/// use arrow2::array::PrimitiveArray;
///
/// let a = PrimitiveArray::from([Some(100i8), Some(0x10i8), Some(100i8)]);
/// let b = PrimitiveArray::from([Some(0i8), Some(0x10i8), Some(0i8)]);
/// let result = wrapping_mul(&a, &b);
/// let expected = PrimitiveArray::from([Some(0), Some(0), Some(0)]);
/// assert_eq!(result, expected);
/// ```
pub fn wrapping_mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingMul<Output = T>,
{
let op = move |a: T, b: T| a.wrapping_mul(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
/// Checked multiplication of two primitive arrays. If the result from the
/// multiplications overflows, the validity for that index is changed
/// returned.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::checked_mul;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[Some(100i8), Some(100i8), Some(100i8)]);
/// let b = Int8Array::from(&[Some(1i8), Some(100i8), Some(1i8)]);
/// let result = checked_mul(&a, &b);
/// let expected = Int8Array::from(&[Some(100i8), None, Some(100i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn checked_mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedMul<Output = T>,
{
let op = move |a: T, b: T| a.checked_mul(&b);
binary_checked(lhs, rhs, lhs.data_type().clone(), op)
}
/// Saturating multiplication of two primitive arrays. If the result from the
/// multiplication overflows, the result for the
/// operation will be the saturated value.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::saturating_mul;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[Some(-100i8)]);
/// let b = Int8Array::from(&[Some(100i8)]);
/// let result = saturating_mul(&a, &b);
/// let expected = Int8Array::from(&[Some(-128)]);
/// assert_eq!(result, expected);
/// ```
pub fn saturating_mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingMul<Output = T>,
{
let op = move |a: T, b: T| a.saturating_mul(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
/// Overflowing multiplication of two primitive arrays. If the result from the
/// mul overflows, the result for the operation will be an array with
/// overflowed values and a validity array indicating the overflowing elements
/// from the array.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::overflowing_mul;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[Some(1i8), Some(-100i8)]);
/// let b = Int8Array::from(&[Some(1i8), Some(100i8)]);
/// let (result, overflow) = overflowing_mul(&a, &b);
/// let expected = Int8Array::from(&[Some(1i8), Some(-16i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn overflowing_mul<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingMul<Output = T>,
{
let op = move |a: T, b: T| a.overflowing_mul(&b);
binary_with_bitmap(lhs, rhs, lhs.data_type().clone(), op)
}
// Implementation of ArrayMul trait for PrimitiveArrays
impl<T> ArrayMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + Mul<Output = T>,
{
fn mul(&self, rhs: &PrimitiveArray<T>) -> Self {
mul(self, rhs)
}
}
impl<T> ArrayWrappingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + WrappingMul<Output = T>,
{
fn wrapping_mul(&self, rhs: &PrimitiveArray<T>) -> Self {
wrapping_mul(self, rhs)
}
}
// Implementation of ArrayCheckedMul trait for PrimitiveArrays
impl<T> ArrayCheckedMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedMul<Output = T>,
{
fn checked_mul(&self, rhs: &PrimitiveArray<T>) -> Self {
checked_mul(self, rhs)
}
}
// Implementation of ArraySaturatingMul trait for PrimitiveArrays
impl<T> ArraySaturatingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingMul<Output = T>,
{
fn saturating_mul(&self, rhs: &PrimitiveArray<T>) -> Self {
saturating_mul(self, rhs)
}
}
// Implementation of ArraySaturatingMul trait for PrimitiveArrays
impl<T> ArrayOverflowingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingMul<Output = T>,
{
fn overflowing_mul(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap) {
overflowing_mul(self, rhs)
}
}
/// Multiply a scalar T to a primitive array of type T.
/// Panics if the multiplication of the values overflows.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::mul_scalar;
/// use arrow2::array::Int32Array;
///
/// let a = Int32Array::from(&[None, Some(6), None, Some(6)]);
/// let result = mul_scalar(&a, &2i32);
/// let expected = Int32Array::from(&[None, Some(12), None, Some(12)]);
/// assert_eq!(result, expected)
/// ```
pub fn mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + Mul<Output = T>,
{
let rhs = *rhs;
unary(lhs, |a| a * rhs, lhs.data_type().clone())
}
/// Wrapping multiplication of a scalar T to a [`PrimitiveArray`] of type T.
/// It do nothing if the result overflows.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::wrapping_mul_scalar;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[None, Some(0x10)]);
/// let result = wrapping_mul_scalar(&a, &0x10);
/// let expected = Int8Array::from(&[None, Some(0)]);
/// assert_eq!(result, expected);
/// ```
pub fn wrapping_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingMul<Output = T>,
{
unary(lhs, |a| a.wrapping_mul(rhs), lhs.data_type().clone())
}
/// Checked multiplication of a scalar T to a primitive array of type T. If the
/// result from the multiplication overflows, then the validity for that index is
/// changed to None
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::checked_mul_scalar;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[None, Some(100), None, Some(100)]);
/// let result = checked_mul_scalar(&a, &100i8);
/// let expected = Int8Array::from(&[None, None, None, None]);
/// assert_eq!(result, expected);
/// ```
pub fn checked_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedMul<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.checked_mul(&rhs);
unary_checked(lhs, op, lhs.data_type().clone())
}
/// Saturated multiplication of a scalar T to a primitive array of type T. If the
/// result from the mul overflows for this type, then
/// the result will be saturated
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::saturating_mul_scalar;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[Some(-100i8)]);
/// let result = saturating_mul_scalar(&a, &100i8);
/// let expected = Int8Array::from(&[Some(-128i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn saturating_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingMul<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.saturating_mul(&rhs);
unary(lhs, op, lhs.data_type().clone())
}
/// Overflowing multiplication of a scalar T to a primitive array of type T. If
/// the result from the mul overflows for this type,
/// then the result will be an array with overflowed values and a validity
/// array indicating the overflowing elements from the array
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::basic::overflowing_mul_scalar;
/// use arrow2::array::Int8Array;
///
/// let a = Int8Array::from(&[Some(1i8), Some(100i8)]);
/// let (result, overflow) = overflowing_mul_scalar(&a, &100i8);
/// let expected = Int8Array::from(&[Some(100i8), Some(16i8)]);
/// assert_eq!(result, expected);
/// ```
pub fn overflowing_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingMul<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.overflowing_mul(&rhs);
unary_with_bitmap(lhs, op, lhs.data_type().clone())
}
- src/compute/arithmetics/basic/rem.rs
- src/compute/arithmetics/basic/sub.rs
- src/compute/arithmetics/basic/pow.rs
- src/compute/arithmetics/mod.rs
- src/compute/cast/primitive_to.rs
- src/compute/nullif.rs
- src/compute/arithmetics/decimal/add.rs
- src/compute/arithmetics/decimal/sub.rs
- src/compute/arithmetics/time.rs
- src/compute/arithmetics/basic/div.rs
- src/compute/filter.rs
- src/compute/take/primitive.rs
- src/compute/sort/primitive/sort.rs
- src/array/growable/primitive.rs
- src/compute/arithmetics/decimal/div.rs
- src/compute/arithmetics/decimal/mul.rs
- src/compute/contains.rs
- src/compute/cast/decimal_to.rs
- src/array/primitive/fmt.rs
sourcepub fn value(&self, i: usize) -> T
pub fn value(&self, i: usize) -> T
Returns the value at slot i
.
Equivalent to self.values()[i]
. The value of a null slot is undetermined (it can be anything).
Panic
This function panics iff i >= self.len
.
Examples found in repository?
More examples
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
fn compare_primitives<T: NativeType + Ord>(left: &dyn Array, right: &dyn Array) -> DynComparator {
let left = left
.as_any()
.downcast_ref::<PrimitiveArray<T>>()
.unwrap()
.clone();
let right = right
.as_any()
.downcast_ref::<PrimitiveArray<T>>()
.unwrap()
.clone();
Box::new(move |i, j| total_cmp(&left.value(i), &right.value(j)))
}
fn compare_boolean(left: &dyn Array, right: &dyn Array) -> DynComparator {
let left = left
.as_any()
.downcast_ref::<BooleanArray>()
.unwrap()
.clone();
let right = right
.as_any()
.downcast_ref::<BooleanArray>()
.unwrap()
.clone();
Box::new(move |i, j| left.value(i).cmp(&right.value(j)))
}
fn compare_f32(left: &dyn Array, right: &dyn Array) -> DynComparator {
let left = left
.as_any()
.downcast_ref::<PrimitiveArray<f32>>()
.unwrap()
.clone();
let right = right
.as_any()
.downcast_ref::<PrimitiveArray<f32>>()
.unwrap()
.clone();
Box::new(move |i, j| total_cmp_f32(&left.value(i), &right.value(j)))
}
fn compare_f64(left: &dyn Array, right: &dyn Array) -> DynComparator {
let left = left
.as_any()
.downcast_ref::<PrimitiveArray<f64>>()
.unwrap()
.clone();
let right = right
.as_any()
.downcast_ref::<PrimitiveArray<f64>>()
.unwrap()
.clone();
Box::new(move |i, j| total_cmp_f64(&left.value(i), &right.value(j)))
}
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
pub fn get_write_value<'a, T: NativeType, F: Write>(
array: &'a PrimitiveArray<T>,
) -> Box<dyn Fn(&mut F, usize) -> Result + 'a> {
use crate::datatypes::DataType::*;
match array.data_type().to_logical_type() {
Int8 => Box::new(|f, index| write!(f, "{}", array.value(index))),
Int16 => Box::new(|f, index| write!(f, "{}", array.value(index))),
Int32 => Box::new(|f, index| write!(f, "{}", array.value(index))),
Int64 => Box::new(|f, index| write!(f, "{}", array.value(index))),
UInt8 => Box::new(|f, index| write!(f, "{}", array.value(index))),
UInt16 => Box::new(|f, index| write!(f, "{}", array.value(index))),
UInt32 => Box::new(|f, index| write!(f, "{}", array.value(index))),
UInt64 => Box::new(|f, index| write!(f, "{}", array.value(index))),
Float16 => unreachable!(),
Float32 => Box::new(|f, index| write!(f, "{}", array.value(index))),
Float64 => Box::new(|f, index| write!(f, "{}", array.value(index))),
Date32 => {
dyn_primitive!(array, i32, temporal_conversions::date32_to_date)
}
Date64 => {
dyn_primitive!(array, i64, temporal_conversions::date64_to_date)
}
Time32(TimeUnit::Second) => {
dyn_primitive!(array, i32, temporal_conversions::time32s_to_time)
}
Time32(TimeUnit::Millisecond) => {
dyn_primitive!(array, i32, temporal_conversions::time32ms_to_time)
}
Time32(_) => unreachable!(), // remaining are not valid
Time64(TimeUnit::Microsecond) => {
dyn_primitive!(array, i64, temporal_conversions::time64us_to_time)
}
Time64(TimeUnit::Nanosecond) => {
dyn_primitive!(array, i64, temporal_conversions::time64ns_to_time)
}
Time64(_) => unreachable!(), // remaining are not valid
Timestamp(time_unit, tz) => {
if let Some(tz) = tz {
let timezone = temporal_conversions::parse_offset(tz);
match timezone {
Ok(timezone) => {
dyn_primitive!(array, i64, |time| {
temporal_conversions::timestamp_to_datetime(time, *time_unit, &timezone)
})
}
#[cfg(feature = "chrono-tz")]
Err(_) => {
let timezone = temporal_conversions::parse_offset_tz(tz);
match timezone {
Ok(timezone) => dyn_primitive!(array, i64, |time| {
temporal_conversions::timestamp_to_datetime(
time, *time_unit, &timezone,
)
}),
Err(_) => {
let tz = tz.clone();
Box::new(move |f, index| {
write!(f, "{} ({})", array.value(index), tz)
})
}
}
}
#[cfg(not(feature = "chrono-tz"))]
_ => {
let tz = tz.clone();
Box::new(move |f, index| write!(f, "{} ({})", array.value(index), tz))
}
}
} else {
dyn_primitive!(array, i64, |time| {
temporal_conversions::timestamp_to_naive_datetime(time, *time_unit)
})
}
}
Interval(IntervalUnit::YearMonth) => {
dyn_primitive!(array, i32, |x| format!("{}m", x))
}
Interval(IntervalUnit::DayTime) => {
dyn_primitive!(array, days_ms, |x: days_ms| format!(
"{}d{}ms",
x.days(),
x.milliseconds()
))
}
Interval(IntervalUnit::MonthDayNano) => {
dyn_primitive!(array, months_days_ns, |x: months_days_ns| format!(
"{}m{}d{}ns",
x.months(),
x.days(),
x.ns()
))
}
Duration(TimeUnit::Second) => dyn_primitive!(array, i64, |x| format!("{}s", x)),
Duration(TimeUnit::Millisecond) => dyn_primitive!(array, i64, |x| format!("{}ms", x)),
Duration(TimeUnit::Microsecond) => dyn_primitive!(array, i64, |x| format!("{}us", x)),
Duration(TimeUnit::Nanosecond) => dyn_primitive!(array, i64, |x| format!("{}ns", x)),
Decimal(_, scale) => {
// The number 999.99 has a precision of 5 and scale of 2
let scale = *scale as u32;
let factor = 10i128.pow(scale);
let display = move |x: i128| {
let base = x / factor;
let decimals = (x - base * factor).abs();
format!("{}.{}", base, decimals)
};
dyn_primitive!(array, i128, display)
}
Decimal256(_, scale) => {
let scale = *scale as u32;
let factor = (ethnum::I256::ONE * 10).pow(scale);
let display = move |x: i256| {
let base = x.0 / factor;
let decimals = (x.0 - base * factor).abs();
format!("{}.{}", base, decimals)
};
dyn_primitive!(array, i256, display)
}
_ => unreachable!(),
}
}
sourcepub unsafe fn value_unchecked(&self, i: usize) -> T
pub unsafe fn value_unchecked(&self, i: usize) -> T
Returns the value at index i
.
The value on null slots is undetermined (it can be anything).
Safety
Caller must be sure that i < self.len()
Examples found in repository?
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
pub(super) fn indices_sorted_unstable_by_dictionary<I: Index, K: DictionaryKey, O: Offset>(
array: &DictionaryArray<K>,
options: &SortOptions,
limit: Option<usize>,
) -> PrimitiveArray<I> {
let keys = array.keys();
let dict = array
.values()
.as_any()
.downcast_ref::<Utf8Array<O>>()
.unwrap();
let get = |index| unsafe {
// safety: indices_sorted_unstable_by is guaranteed to get items in bounds
let index = keys.value_unchecked(index);
// safety: dictionaries are guaranteed to have valid usize keys
let index = index.as_usize();
// safety: dictionaries are guaranteed to have keys in bounds
dict.value_unchecked(index)
};
let cmp = |lhs: &&str, rhs: &&str| lhs.cmp(rhs);
common::indices_sorted_unstable_by(array.validity(), get, cmp, array.len(), options, limit)
}
sourcepub fn slice(&self, offset: usize, length: usize) -> Self
pub fn slice(&self, offset: usize, length: usize) -> Self
Returns a clone of this PrimitiveArray
sliced by an offset and length.
Implementation
This operation is O(1)
as it amounts to increase two ref counts.
Examples
use arrow2::array::PrimitiveArray;
let array = PrimitiveArray::from_vec(vec![1, 2, 3]);
assert_eq!(format!("{:?}", array), "Int32[1, 2, 3]");
let sliced = array.slice(1, 1);
assert_eq!(format!("{:?}", sliced), "Int32[2]");
// note: `sliced` and `array` share the same memory region.
Panic
This function panics iff offset + length > self.len()
.
Examples found in repository?
More examples
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
pub fn array_to_page<T, R>(
array: &PrimitiveArray<T>,
options: WriteOptions,
type_: PrimitiveType,
nested: &[Nested],
) -> Result<DataPage>
where
T: ArrowNativeType,
R: NativeType,
T: num_traits::AsPrimitive<R>,
{
let is_optional = is_nullable(&type_.field_info);
let mut buffer = vec![];
// we slice the leaf by the offsets as dremel only computes lengths and thus
// does NOT take the starting offset into account.
// By slicing the leaf array we also don't write too many values.
let (start, len) = slice_nested_leaf(nested);
let (repetition_levels_byte_length, definition_levels_byte_length) =
nested::write_rep_and_def(options.version, nested, &mut buffer, start)?;
let array = array.slice(start, len);
let buffer = encode_plain(&array, is_optional, buffer);
let statistics = if options.write_statistics {
Some(serialize_statistics(&build_statistics(
&array,
type_.clone(),
)))
} else {
None
};
utils::build_plain_page(
buffer,
nested::num_values(nested),
nested[0].len(),
array.null_count(),
repetition_levels_byte_length,
definition_levels_byte_length,
statistics,
type_,
options,
Encoding::Plain,
)
}
sourcepub unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Self
pub unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Self
Returns a clone of this PrimitiveArray
sliced by an offset and length.
Implementation
This operation is O(1)
as it amounts to increase two ref counts.
Safety
The caller must ensure that offset + length <= self.len()
.
Examples found in repository?
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
pub fn slice(&self, offset: usize, length: usize) -> Self {
assert!(
offset + length <= self.len(),
"offset + length may not exceed length of array"
);
unsafe { self.slice_unchecked(offset, length) }
}
/// Returns a clone of this [`PrimitiveArray`] sliced by an offset and length.
/// # Implementation
/// This operation is `O(1)` as it amounts to increase two ref counts.
/// # Safety
/// The caller must ensure that `offset + length <= self.len()`.
#[inline]
#[must_use]
pub unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Self {
let validity = self
.validity
.clone()
.map(|bitmap| bitmap.slice_unchecked(offset, length))
.and_then(|bitmap| (bitmap.unset_bits() > 0).then(|| bitmap));
Self {
data_type: self.data_type.clone(),
values: self.values.clone().slice_unchecked(offset, length),
validity,
}
}
/// Returns this [`PrimitiveArray`] with a new validity.
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
#[must_use]
pub fn with_validity(mut self, validity: Option<Bitmap>) -> Self {
self.set_validity(validity);
self
}
/// Sets the validity of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
pub fn set_validity(&mut self, validity: Option<Bitmap>) {
if matches!(&validity, Some(bitmap) if bitmap.len() != self.len()) {
panic!("validity's length must be equal to the array's length")
}
self.validity = validity;
}
/// Returns this [`PrimitiveArray`] with new values.
/// # Panics
/// This function panics iff `values.len() != self.len()`.
#[must_use]
pub fn with_values(mut self, values: Buffer<T>) -> Self {
self.set_values(values);
self
}
/// Update the values of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `values.len() != self.len()`.
pub fn set_values(&mut self, values: Buffer<T>) {
assert_eq!(
values.len(),
self.len(),
"values' length must be equal to this arrays' length"
);
self.values = values;
}
/// Applies a function `f` to the validity of this array.
///
/// This is an API to leverage clone-on-write
/// # Panics
/// This function panics if the function `f` modifies the length of the [`Bitmap`].
pub fn apply_validity<F: FnOnce(Bitmap) -> Bitmap>(&mut self, f: F) {
if let Some(validity) = std::mem::take(&mut self.validity) {
self.set_validity(Some(f(validity)))
}
}
/// Returns an option of a mutable reference to the values of this [`PrimitiveArray`].
pub fn get_mut_values(&mut self) -> Option<&mut [T]> {
self.values.get_mut().map(|x| x.as_mut())
}
/// Returns its internal representation
#[must_use]
pub fn into_inner(self) -> (DataType, Buffer<T>, Option<Bitmap>) {
let Self {
data_type,
values,
validity,
} = self;
(data_type, values, validity)
}
/// Try to convert this [`PrimitiveArray`] to a [`MutablePrimitiveArray`] via copy-on-write semantics.
///
/// A [`PrimitiveArray`] is backed by a [`Buffer`] and [`Bitmap`] which are essentially `Arc<Vec<_>>`.
/// This function returns a [`MutablePrimitiveArray`] (via [`std::sync::Arc::get_mut`]) iff both values
/// and validity have not been cloned / are unique references to their underlying vectors.
///
/// This function is primarily used to re-use memory regions.
#[must_use]
pub fn into_mut(mut self) -> Either<Self, MutablePrimitiveArray<T>> {
use Either::*;
if let Some(bitmap) = self.validity {
match bitmap.into_mut() {
Left(bitmap) => Left(PrimitiveArray::new(
self.data_type,
self.values,
Some(bitmap),
)),
Right(mutable_bitmap) => match self.values.get_mut().map(std::mem::take) {
Some(values) => Right(
MutablePrimitiveArray::try_new(
self.data_type,
values,
Some(mutable_bitmap),
)
.unwrap(),
),
None => Left(PrimitiveArray::new(
self.data_type,
self.values,
Some(mutable_bitmap.into()),
)),
},
}
} else {
match self.values.get_mut().map(std::mem::take) {
Some(values) => {
Right(MutablePrimitiveArray::try_new(self.data_type, values, None).unwrap())
}
None => Left(PrimitiveArray::new(self.data_type, self.values, None)),
}
}
}
/// Returns a new empty (zero-length) [`PrimitiveArray`].
pub fn new_empty(data_type: DataType) -> Self {
Self::new(data_type, Buffer::new(), None)
}
/// Returns a new [`PrimitiveArray`] where all slots are null / `None`.
#[inline]
pub fn new_null(data_type: DataType, length: usize) -> Self {
Self::new(
data_type,
vec![T::default(); length].into(),
Some(Bitmap::new_zeroed(length)),
)
}
/// Creates a (non-null) [`PrimitiveArray`] from an iterator of values.
/// # Implementation
/// This does not assume that the iterator has a known length.
pub fn from_values<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self::new(T::PRIMITIVE.into(), Vec::<T>::from_iter(iter).into(), None)
}
/// Creates a (non-null) [`PrimitiveArray`] from a slice of values.
/// # Implementation
/// This is essentially a memcopy and is thus `O(N)`
pub fn from_slice<P: AsRef<[T]>>(slice: P) -> Self {
Self::new(
T::PRIMITIVE.into(),
Vec::<T>::from(slice.as_ref()).into(),
None,
)
}
/// Creates a (non-null) [`PrimitiveArray`] from a [`TrustedLen`] of values.
/// # Implementation
/// This does not assume that the iterator has a known length.
pub fn from_trusted_len_values_iter<I: TrustedLen<Item = T>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_values_iter(iter).into()
}
/// Creates a new [`PrimitiveArray`] from an iterator over values
/// # Safety
/// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
/// I.e. that `size_hint().1` correctly reports its length.
pub unsafe fn from_trusted_len_values_iter_unchecked<I: Iterator<Item = T>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_values_iter_unchecked(iter).into()
}
/// Creates a [`PrimitiveArray`] from a [`TrustedLen`] of optional values.
pub fn from_trusted_len_iter<I: TrustedLen<Item = Option<T>>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_iter(iter).into()
}
/// Creates a [`PrimitiveArray`] from an iterator of optional values.
/// # Safety
/// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
/// I.e. that `size_hint().1` correctly reports its length.
pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = Option<T>>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_iter_unchecked(iter).into()
}
/// Boxes self into a [`Box<dyn Array>`].
pub fn boxed(self) -> Box<dyn Array> {
Box::new(self)
}
/// Boxes self into a [`std::sync::Arc<dyn Array>`].
pub fn arced(self) -> std::sync::Arc<dyn Array> {
std::sync::Arc::new(self)
}
/// Alias for `Self::try_new(..).unwrap()`.
/// # Panics
/// This function errors iff:
/// * The validity is not `None` and its length is different from `values`'s length
/// * The `data_type`'s [`PhysicalType`] is not equal to [`PhysicalType::Primitive`].
pub fn new(data_type: DataType, values: Buffer<T>, validity: Option<Bitmap>) -> Self {
Self::try_new(data_type, values, validity).unwrap()
}
}
impl<T: NativeType> Array for PrimitiveArray<T> {
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn len(&self) -> usize {
self.values.len()
}
#[inline]
fn data_type(&self) -> &DataType {
self.data_type()
}
fn validity(&self) -> Option<&Bitmap> {
self.validity.as_ref()
}
fn slice(&self, offset: usize, length: usize) -> Box<dyn Array> {
Box::new(self.slice(offset, length))
}
unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Box<dyn Array> {
Box::new(self.slice_unchecked(offset, length))
}
More examples
sourcepub fn with_validity(self, validity: Option<Bitmap>) -> Self
pub fn with_validity(self, validity: Option<Bitmap>) -> Self
Returns this PrimitiveArray
with a new validity.
Panics
This function panics iff validity.len() != self.len()
.
Examples found in repository?
More examples
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
pub fn eq_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity_lhs = lhs.validity().cloned();
let validity_rhs = rhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let rhs = rhs.clone().with_validity(None);
let out = compare_op(&lhs, &rhs, |a, b| a.eq(b));
finish_eq_validities(out, validity_lhs, validity_rhs)
}
/// Perform `left == right` operation on an array and a scalar value.
pub fn eq_scalar<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
compare_op_scalar(lhs, rhs, |a, b| a.eq(b))
}
/// Perform `left == right` operation on an array and a scalar value and include validities in comparison.
pub fn eq_scalar_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity = lhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let out = compare_op_scalar(&lhs, rhs, |a, b| a.eq(b));
finish_eq_validities(out, validity, None)
}
/// Perform `left != right` operation on two arrays.
pub fn neq<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
compare_op(lhs, rhs, |a, b| a.neq(b))
}
/// Perform `left != right` operation on two arrays and include validities in comparison.
pub fn neq_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity_lhs = lhs.validity().cloned();
let validity_rhs = rhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let rhs = rhs.clone().with_validity(None);
let out = compare_op(&lhs, &rhs, |a, b| a.neq(b));
finish_neq_validities(out, validity_lhs, validity_rhs)
}
/// Perform `left != right` operation on an array and a scalar value.
pub fn neq_scalar<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
compare_op_scalar(lhs, rhs, |a, b| a.neq(b))
}
/// Perform `left != right` operation on an array and a scalar value and include validities in comparison.
pub fn neq_scalar_and_validity<T>(lhs: &PrimitiveArray<T>, rhs: T) -> BooleanArray
where
T: NativeType + Simd8,
T::Simd: Simd8PartialEq,
{
let validity = lhs.validity().cloned();
let lhs = lhs.clone().with_validity(None);
let out = compare_op_scalar(&lhs, rhs, |a, b| a.neq(b));
finish_neq_validities(out, validity, None)
}
sourcepub fn set_validity(&mut self, validity: Option<Bitmap>)
pub fn set_validity(&mut self, validity: Option<Bitmap>)
Sets the validity of this PrimitiveArray
.
Panics
This function panics iff validity.len() != self.len()
.
Examples found in repository?
More examples
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
pub fn with_validity(mut self, validity: Option<Bitmap>) -> Self {
self.set_validity(validity);
self
}
/// Sets the validity of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
pub fn set_validity(&mut self, validity: Option<Bitmap>) {
if matches!(&validity, Some(bitmap) if bitmap.len() != self.len()) {
panic!("validity's length must be equal to the array's length")
}
self.validity = validity;
}
/// Returns this [`PrimitiveArray`] with new values.
/// # Panics
/// This function panics iff `values.len() != self.len()`.
#[must_use]
pub fn with_values(mut self, values: Buffer<T>) -> Self {
self.set_values(values);
self
}
/// Update the values of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `values.len() != self.len()`.
pub fn set_values(&mut self, values: Buffer<T>) {
assert_eq!(
values.len(),
self.len(),
"values' length must be equal to this arrays' length"
);
self.values = values;
}
/// Applies a function `f` to the validity of this array.
///
/// This is an API to leverage clone-on-write
/// # Panics
/// This function panics if the function `f` modifies the length of the [`Bitmap`].
pub fn apply_validity<F: FnOnce(Bitmap) -> Bitmap>(&mut self, f: F) {
if let Some(validity) = std::mem::take(&mut self.validity) {
self.set_validity(Some(f(validity)))
}
}
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
pub fn binary<T, D, F>(lhs: &mut PrimitiveArray<T>, rhs: &PrimitiveArray<D>, op: F)
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> T,
{
check_same_len(lhs, rhs).unwrap();
// both for the validity and for the values
// we branch to check if we can mutate in place
// if we can, great that is fastest.
// if we cannot, we allocate a new buffer and assign values to that
// new buffer, that is benchmarked to be ~2x faster than first memcpy and assign in place
// for the validity bits it can be much faster as we might need to iterate all bits if the
// bitmap has an offset.
if let Some(rhs) = rhs.validity() {
if lhs.validity().is_none() {
lhs.set_validity(Some(rhs.clone()));
} else {
lhs.apply_validity(|bitmap| {
match bitmap.into_mut() {
Either::Left(immutable) => {
// alloc new region
&immutable & rhs
}
Either::Right(mutable) => {
// mutate in place
(mutable & rhs).into()
}
}
});
}
};
if let Some(values) = lhs.get_mut_values() {
// mutate values in place
values
.iter_mut()
.zip(rhs.values().iter())
.for_each(|(l, r)| *l = op(*l, *r));
} else {
// alloc new region
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Vec<_>>();
lhs.set_values(values.into());
}
}
sourcepub fn with_values(self, values: Buffer<T>) -> Self
pub fn with_values(self, values: Buffer<T>) -> Self
Returns this PrimitiveArray
with new values.
Panics
This function panics iff values.len() != self.len()
.
sourcepub fn set_values(&mut self, values: Buffer<T>)
pub fn set_values(&mut self, values: Buffer<T>)
Update the values of this PrimitiveArray
.
Panics
This function panics iff values.len() != self.len()
.
Examples found in repository?
More examples
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
pub fn unary<I, F>(array: &mut PrimitiveArray<I>, op: F)
where
I: NativeType,
F: Fn(I) -> I,
{
if let Some(values) = array.get_mut_values() {
// mutate in place
values.iter_mut().for_each(|l| *l = op(*l));
} else {
// alloc and write to new region
let values = array.values().iter().map(|l| op(*l)).collect::<Vec<_>>();
array.set_values(values.into());
}
}
/// Applies a binary function to two [`PrimitiveArray`]s, optionally in-place, returning
/// a new [`PrimitiveArray`].
///
/// # Implementation
/// This function tries to apply the function directly to the values of the array.
/// If that region is shared, this function creates a new region and writes to it.
/// # Panics
/// This function panics iff
/// * the arrays have a different length.
/// * the function itself panics.
#[inline]
pub fn binary<T, D, F>(lhs: &mut PrimitiveArray<T>, rhs: &PrimitiveArray<D>, op: F)
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> T,
{
check_same_len(lhs, rhs).unwrap();
// both for the validity and for the values
// we branch to check if we can mutate in place
// if we can, great that is fastest.
// if we cannot, we allocate a new buffer and assign values to that
// new buffer, that is benchmarked to be ~2x faster than first memcpy and assign in place
// for the validity bits it can be much faster as we might need to iterate all bits if the
// bitmap has an offset.
if let Some(rhs) = rhs.validity() {
if lhs.validity().is_none() {
lhs.set_validity(Some(rhs.clone()));
} else {
lhs.apply_validity(|bitmap| {
match bitmap.into_mut() {
Either::Left(immutable) => {
// alloc new region
&immutable & rhs
}
Either::Right(mutable) => {
// mutate in place
(mutable & rhs).into()
}
}
});
}
};
if let Some(values) = lhs.get_mut_values() {
// mutate values in place
values
.iter_mut()
.zip(rhs.values().iter())
.for_each(|(l, r)| *l = op(*l, *r));
} else {
// alloc new region
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Vec<_>>();
lhs.set_values(values.into());
}
}
sourcepub fn apply_validity<F: FnOnce(Bitmap) -> Bitmap>(&mut self, f: F)
pub fn apply_validity<F: FnOnce(Bitmap) -> Bitmap>(&mut self, f: F)
Applies a function f
to the validity of this array.
This is an API to leverage clone-on-write
Panics
This function panics if the function f
modifies the length of the Bitmap
.
Examples found in repository?
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
pub fn binary<T, D, F>(lhs: &mut PrimitiveArray<T>, rhs: &PrimitiveArray<D>, op: F)
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> T,
{
check_same_len(lhs, rhs).unwrap();
// both for the validity and for the values
// we branch to check if we can mutate in place
// if we can, great that is fastest.
// if we cannot, we allocate a new buffer and assign values to that
// new buffer, that is benchmarked to be ~2x faster than first memcpy and assign in place
// for the validity bits it can be much faster as we might need to iterate all bits if the
// bitmap has an offset.
if let Some(rhs) = rhs.validity() {
if lhs.validity().is_none() {
lhs.set_validity(Some(rhs.clone()));
} else {
lhs.apply_validity(|bitmap| {
match bitmap.into_mut() {
Either::Left(immutable) => {
// alloc new region
&immutable & rhs
}
Either::Right(mutable) => {
// mutate in place
(mutable & rhs).into()
}
}
});
}
};
if let Some(values) = lhs.get_mut_values() {
// mutate values in place
values
.iter_mut()
.zip(rhs.values().iter())
.for_each(|(l, r)| *l = op(*l, *r));
} else {
// alloc new region
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Vec<_>>();
lhs.set_values(values.into());
}
}
sourcepub fn get_mut_values(&mut self) -> Option<&mut [T]>
pub fn get_mut_values(&mut self) -> Option<&mut [T]>
Returns an option of a mutable reference to the values of this PrimitiveArray
.
Examples found in repository?
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
pub fn unary<I, F>(array: &mut PrimitiveArray<I>, op: F)
where
I: NativeType,
F: Fn(I) -> I,
{
if let Some(values) = array.get_mut_values() {
// mutate in place
values.iter_mut().for_each(|l| *l = op(*l));
} else {
// alloc and write to new region
let values = array.values().iter().map(|l| op(*l)).collect::<Vec<_>>();
array.set_values(values.into());
}
}
/// Applies a binary function to two [`PrimitiveArray`]s, optionally in-place, returning
/// a new [`PrimitiveArray`].
///
/// # Implementation
/// This function tries to apply the function directly to the values of the array.
/// If that region is shared, this function creates a new region and writes to it.
/// # Panics
/// This function panics iff
/// * the arrays have a different length.
/// * the function itself panics.
#[inline]
pub fn binary<T, D, F>(lhs: &mut PrimitiveArray<T>, rhs: &PrimitiveArray<D>, op: F)
where
T: NativeType,
D: NativeType,
F: Fn(T, D) -> T,
{
check_same_len(lhs, rhs).unwrap();
// both for the validity and for the values
// we branch to check if we can mutate in place
// if we can, great that is fastest.
// if we cannot, we allocate a new buffer and assign values to that
// new buffer, that is benchmarked to be ~2x faster than first memcpy and assign in place
// for the validity bits it can be much faster as we might need to iterate all bits if the
// bitmap has an offset.
if let Some(rhs) = rhs.validity() {
if lhs.validity().is_none() {
lhs.set_validity(Some(rhs.clone()));
} else {
lhs.apply_validity(|bitmap| {
match bitmap.into_mut() {
Either::Left(immutable) => {
// alloc new region
&immutable & rhs
}
Either::Right(mutable) => {
// mutate in place
(mutable & rhs).into()
}
}
});
}
};
if let Some(values) = lhs.get_mut_values() {
// mutate values in place
values
.iter_mut()
.zip(rhs.values().iter())
.for_each(|(l, r)| *l = op(*l, *r));
} else {
// alloc new region
let values = lhs
.values()
.iter()
.zip(rhs.values().iter())
.map(|(l, r)| op(*l, *r))
.collect::<Vec<_>>();
lhs.set_values(values.into());
}
}
sourcepub fn into_inner(self) -> (DataType, Buffer<T>, Option<Bitmap>)
pub fn into_inner(self) -> (DataType, Buffer<T>, Option<Bitmap>)
Returns its internal representation
sourcepub fn into_mut(self) -> Either<Self, MutablePrimitiveArray<T>> ⓘ
pub fn into_mut(self) -> Either<Self, MutablePrimitiveArray<T>> ⓘ
Try to convert this PrimitiveArray
to a MutablePrimitiveArray
via copy-on-write semantics.
A PrimitiveArray
is backed by a Buffer
and Bitmap
which are essentially Arc<Vec<_>>
.
This function returns a MutablePrimitiveArray
(via std::sync::Arc::get_mut
) iff both values
and validity have not been cloned / are unique references to their underlying vectors.
This function is primarily used to re-use memory regions.
sourcepub fn new_empty(data_type: DataType) -> Self
pub fn new_empty(data_type: DataType) -> Self
Returns a new empty (zero-length) PrimitiveArray
.
sourcepub fn new_null(data_type: DataType, length: usize) -> Self
pub fn new_null(data_type: DataType, length: usize) -> Self
Returns a new PrimitiveArray
where all slots are null / None
.
Examples found in repository?
More examples
104 105 106 107 108 109 110 111 112 113 114 115
fn binary_scalar<T: NativeType, F: Fn(&PrimitiveArray<T>, &T) -> PrimitiveArray<T>>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveScalar<T>,
op: F,
) -> PrimitiveArray<T> {
let rhs = if let Some(rhs) = *rhs.value() {
rhs
} else {
return PrimitiveArray::<T>::new_null(lhs.data_type().clone(), lhs.len());
};
op(lhs, &rhs)
}
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
pub fn add_duration_scalar<T>(
time: &PrimitiveArray<T>,
duration: &PrimitiveScalar<i64>,
) -> PrimitiveArray<T>
where
f64: AsPrimitive<T>,
T: NativeType + Add<T, Output = T>,
{
let scale = create_scale(time.data_type(), duration.data_type()).unwrap();
let duration = if let Some(duration) = *duration.value() {
duration
} else {
return PrimitiveArray::<T>::new_null(time.data_type().clone(), time.len());
};
// Closure for the binary operation. The closure contains the scale
// required to add a duration to the timestamp array.
let op = move |a: T| a + (duration as f64 * scale).as_();
unary(time, op, time.data_type().clone())
}
/// Subtract a duration to a time array (Timestamp, Time and Date). The timeunit
/// enum is used to scale correctly both arrays; adding seconds with seconds,
/// or milliseconds with milliseconds.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::time::subtract_duration;
/// use arrow2::array::PrimitiveArray;
/// use arrow2::datatypes::{DataType, TimeUnit};
///
/// let timestamp = PrimitiveArray::from([
/// Some(100000i64),
/// Some(200000i64),
/// None,
/// Some(300000i64),
/// ])
/// .to(DataType::Timestamp(
/// TimeUnit::Second,
/// Some("America/New_York".to_string()),
/// ));
///
/// let duration = PrimitiveArray::from([Some(10i64), Some(20i64), None, Some(30i64)])
/// .to(DataType::Duration(TimeUnit::Second));
///
/// let result = subtract_duration(×tamp, &duration);
/// let expected = PrimitiveArray::from([
/// Some(99990i64),
/// Some(199980i64),
/// None,
/// Some(299970i64),
/// ])
/// .to(DataType::Timestamp(
/// TimeUnit::Second,
/// Some("America/New_York".to_string()),
/// ));
///
/// assert_eq!(result, expected);
///
/// ```
pub fn subtract_duration<T>(
time: &PrimitiveArray<T>,
duration: &PrimitiveArray<i64>,
) -> PrimitiveArray<T>
where
f64: AsPrimitive<T>,
T: NativeType + Sub<T, Output = T>,
{
let scale = create_scale(time.data_type(), duration.data_type()).unwrap();
// Closure for the binary operation. The closure contains the scale
// required to add a duration to the timestamp array.
let op = move |a: T, b: i64| a - (b as f64 * scale).as_();
binary(time, duration, time.data_type().clone(), op)
}
/// Subtract a duration to a time array (Timestamp, Time and Date). The timeunit
/// enum is used to scale correctly both arrays; adding seconds with seconds,
/// or milliseconds with milliseconds.
pub fn sub_duration_scalar<T>(
time: &PrimitiveArray<T>,
duration: &PrimitiveScalar<i64>,
) -> PrimitiveArray<T>
where
f64: AsPrimitive<T>,
T: NativeType + Sub<T, Output = T>,
{
let scale = create_scale(time.data_type(), duration.data_type()).unwrap();
let duration = if let Some(duration) = *duration.value() {
duration
} else {
return PrimitiveArray::<T>::new_null(time.data_type().clone(), time.len());
};
let op = move |a: T| a - (duration as f64 * scale).as_();
unary(time, op, time.data_type().clone())
}
/// Calculates the difference between two timestamps returning an array of type
/// Duration. The timeunit enum is used to scale correctly both arrays;
/// subtracting seconds with seconds, or milliseconds with milliseconds.
///
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::time::subtract_timestamps;
/// use arrow2::array::PrimitiveArray;
/// use arrow2::datatypes::{DataType, TimeUnit};
/// let timestamp_a = PrimitiveArray::from([
/// Some(100_010i64),
/// Some(200_020i64),
/// None,
/// Some(300_030i64),
/// ])
/// .to(DataType::Timestamp(TimeUnit::Second, None));
///
/// let timestamp_b = PrimitiveArray::from([
/// Some(100_000i64),
/// Some(200_000i64),
/// None,
/// Some(300_000i64),
/// ])
/// .to(DataType::Timestamp(TimeUnit::Second, None));
///
/// let expected = PrimitiveArray::from([Some(10i64), Some(20i64), None, Some(30i64)])
/// .to(DataType::Duration(TimeUnit::Second));
///
/// let result = subtract_timestamps(×tamp_a, &×tamp_b).unwrap();
/// assert_eq!(result, expected);
/// ```
pub fn subtract_timestamps(
lhs: &PrimitiveArray<i64>,
rhs: &PrimitiveArray<i64>,
) -> Result<PrimitiveArray<i64>> {
// Matching on both data types from both arrays.
// Both timestamps have a Timeunit enum in its data type.
// This enum is used to adjust the scale between the timestamps.
match (lhs.data_type(), rhs.data_type()) {
// Naive timestamp comparison. It doesn't take into account timezones
// from the Timestamp timeunit.
(DataType::Timestamp(timeunit_a, None), DataType::Timestamp(timeunit_b, None)) => {
// Closure for the binary operation. The closure contains the scale
// required to calculate the difference between the timestamps.
let scale = temporal_conversions::timeunit_scale(*timeunit_a, *timeunit_b);
let op = move |a, b| a - (b as f64 * scale) as i64;
Ok(binary(lhs, rhs, DataType::Duration(*timeunit_a), op))
}
_ => Err(Error::InvalidArgumentError(
"Incorrect data type for the arguments".to_string(),
)),
}
}
/// Calculates the difference between two timestamps as [`DataType::Duration`] with the same time scale.
pub fn sub_timestamps_scalar(
lhs: &PrimitiveArray<i64>,
rhs: &PrimitiveScalar<i64>,
) -> Result<PrimitiveArray<i64>> {
let (scale, timeunit_a) =
if let (DataType::Timestamp(timeunit_a, None), DataType::Timestamp(timeunit_b, None)) =
(lhs.data_type(), rhs.data_type())
{
(
temporal_conversions::timeunit_scale(*timeunit_a, *timeunit_b),
timeunit_a,
)
} else {
return Err(Error::InvalidArgumentError(
"sub_timestamps_scalar requires both arguments to be timestamps without timezone"
.to_string(),
));
};
let rhs = if let Some(value) = *rhs.value() {
value
} else {
return Ok(PrimitiveArray::<i64>::new_null(
lhs.data_type().clone(),
lhs.len(),
));
};
let op = move |a| a - (rhs as f64 * scale) as i64;
Ok(unary(lhs, op, DataType::Duration(*timeunit_a)))
}
/// Adds an interval to a [`DataType::Timestamp`].
pub fn add_interval(
timestamp: &PrimitiveArray<i64>,
interval: &PrimitiveArray<months_days_ns>,
) -> Result<PrimitiveArray<i64>> {
match timestamp.data_type().to_logical_type() {
DataType::Timestamp(time_unit, Some(timezone_str)) => {
let time_unit = *time_unit;
let timezone = temporal_conversions::parse_offset(timezone_str);
match timezone {
Ok(timezone) => Ok(binary(
timestamp,
interval,
timestamp.data_type().clone(),
|timestamp, interval| {
temporal_conversions::add_interval(
timestamp, time_unit, interval, &timezone,
)
},
)),
#[cfg(feature = "chrono-tz")]
Err(_) => {
let timezone = temporal_conversions::parse_offset_tz(timezone_str)?;
Ok(binary(
timestamp,
interval,
timestamp.data_type().clone(),
|timestamp, interval| {
temporal_conversions::add_interval(
timestamp, time_unit, interval, &timezone,
)
},
))
}
#[cfg(not(feature = "chrono-tz"))]
_ => Err(Error::InvalidArgumentError(format!(
"timezone \"{}\" cannot be parsed (feature chrono-tz is not active)",
timezone_str
))),
}
}
DataType::Timestamp(time_unit, None) => {
let time_unit = *time_unit;
Ok(binary(
timestamp,
interval,
timestamp.data_type().clone(),
|timestamp, interval| {
temporal_conversions::add_naive_interval(timestamp, time_unit, interval)
},
))
}
_ => Err(Error::InvalidArgumentError(
"Adding an interval is only supported for `DataType::Timestamp`".to_string(),
)),
}
}
/// Adds an interval to a [`DataType::Timestamp`].
pub fn add_interval_scalar(
timestamp: &PrimitiveArray<i64>,
interval: &PrimitiveScalar<months_days_ns>,
) -> Result<PrimitiveArray<i64>> {
let interval = if let Some(interval) = *interval.value() {
interval
} else {
return Ok(PrimitiveArray::<i64>::new_null(
timestamp.data_type().clone(),
timestamp.len(),
));
};
match timestamp.data_type().to_logical_type() {
DataType::Timestamp(time_unit, Some(timezone_str)) => {
let time_unit = *time_unit;
let timezone = temporal_conversions::parse_offset(timezone_str);
match timezone {
Ok(timezone) => Ok(unary(
timestamp,
|timestamp| {
temporal_conversions::add_interval(
timestamp, time_unit, interval, &timezone,
)
},
timestamp.data_type().clone(),
)),
#[cfg(feature = "chrono-tz")]
Err(_) => {
let timezone = temporal_conversions::parse_offset_tz(timezone_str)?;
Ok(unary(
timestamp,
|timestamp| {
temporal_conversions::add_interval(
timestamp, time_unit, interval, &timezone,
)
},
timestamp.data_type().clone(),
))
}
#[cfg(not(feature = "chrono-tz"))]
_ => Err(Error::InvalidArgumentError(format!(
"timezone \"{}\" cannot be parsed (feature chrono-tz is not active)",
timezone_str
))),
}
}
DataType::Timestamp(time_unit, None) => {
let time_unit = *time_unit;
Ok(unary(
timestamp,
|timestamp| {
temporal_conversions::add_naive_interval(timestamp, time_unit, interval)
},
timestamp.data_type().clone(),
))
}
_ => Err(Error::InvalidArgumentError(
"Adding an interval is only supported for `DataType::Timestamp`".to_string(),
)),
}
}
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
pub fn div_scalar(lhs: &PrimitiveArray<i128>, rhs: &PrimitiveScalar<i128>) -> PrimitiveArray<i128> {
let (precision, scale) = get_parameters(lhs.data_type(), rhs.data_type()).unwrap();
let rhs = if let Some(rhs) = *rhs.value() {
rhs
} else {
return PrimitiveArray::<i128>::new_null(lhs.data_type().clone(), lhs.len());
};
let scale = 10i128.pow(scale as u32);
let max = max_value(precision);
let op = move |a: i128| {
// The division is done using the numbers without scale.
// The dividend is scaled up to maintain precision after the
// division
// 222.222 --> 222222000
// 123.456 --> 123456
// -------- ---------
// 1.800 <-- 1800
let numeral: i128 = a * scale;
// The division can overflow if the dividend is divided
// by zero.
let res: i128 = numeral.checked_div(rhs).expect("Found division by zero");
assert!(
res.abs() <= max,
"Overflow in multiplication presented for precision {}",
precision
);
res
};
unary(lhs, op, lhs.data_type().clone())
}
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
pub fn mul_scalar(lhs: &PrimitiveArray<i128>, rhs: &PrimitiveScalar<i128>) -> PrimitiveArray<i128> {
let (precision, scale) = get_parameters(lhs.data_type(), rhs.data_type()).unwrap();
let rhs = if let Some(rhs) = *rhs.value() {
rhs
} else {
return PrimitiveArray::<i128>::new_null(lhs.data_type().clone(), lhs.len());
};
let scale = 10i128.pow(scale as u32);
let max = max_value(precision);
let op = move |a: i128| {
// The multiplication between i128 can overflow if they are
// very large numbers. For that reason a checked
// multiplication is used.
let res: i128 = a
.checked_mul(rhs)
.expect("Mayor overflow for multiplication");
// The multiplication is done using the numbers without scale.
// The resulting scale of the value has to be corrected by
// dividing by (10^scale)
// 111.111 --> 111111
// 222.222 --> 222222
// -------- -------
// 24691.308 <-- 24691308642
let res = res / scale;
assert!(
res.abs() <= max,
"Overflow in multiplication presented for precision {}",
precision
);
res
};
unary(lhs, op, lhs.data_type().clone())
}
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
pub fn array_to_page_simple(
array: &dyn Array,
type_: ParquetPrimitiveType,
options: WriteOptions,
encoding: Encoding,
) -> Result<Page> {
let data_type = array.data_type();
if !can_encode(data_type, encoding) {
return Err(Error::InvalidArgumentError(format!(
"The datatype {:?} cannot be encoded by {:?}",
data_type, encoding
)));
}
match data_type.to_logical_type() {
DataType::Boolean => {
boolean::array_to_page(array.as_any().downcast_ref().unwrap(), options, type_)
}
// casts below MUST match the casts done at the metadata (field -> parquet type).
DataType::UInt8 => primitive::array_to_page_integer::<u8, i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::UInt16 => primitive::array_to_page_integer::<u16, i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::UInt32 => primitive::array_to_page_integer::<u32, i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::UInt64 => primitive::array_to_page_integer::<u64, i64>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::Int8 => primitive::array_to_page_integer::<i8, i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::Int16 => primitive::array_to_page_integer::<i16, i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::Int32 | DataType::Date32 | DataType::Time32(_) => {
primitive::array_to_page_integer::<i32, i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
)
}
DataType::Int64
| DataType::Date64
| DataType::Time64(_)
| DataType::Timestamp(_, _)
| DataType::Duration(_) => primitive::array_to_page_integer::<i64, i64>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::Float32 => primitive::array_to_page_plain::<f32, f32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
),
DataType::Float64 => primitive::array_to_page_plain::<f64, f64>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
),
DataType::Utf8 => utf8::array_to_page::<i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::LargeUtf8 => utf8::array_to_page::<i64>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::Binary => binary::array_to_page::<i32>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::LargeBinary => binary::array_to_page::<i64>(
array.as_any().downcast_ref().unwrap(),
options,
type_,
encoding,
),
DataType::Null => {
let array = Int32Array::new_null(DataType::Int32, array.len());
primitive::array_to_page_plain::<i32, i32>(&array, options, type_)
}
DataType::Interval(IntervalUnit::YearMonth) => {
let type_ = type_;
let array = array
.as_any()
.downcast_ref::<PrimitiveArray<i32>>()
.unwrap();
let mut values = Vec::<u8>::with_capacity(12 * array.len());
array.values().iter().for_each(|x| {
let bytes = &x.to_le_bytes();
values.extend_from_slice(bytes);
values.extend_from_slice(&[0; 8]);
});
let array = FixedSizeBinaryArray::new(
DataType::FixedSizeBinary(12),
values.into(),
array.validity().cloned(),
);
let statistics = if options.write_statistics {
Some(fixed_len_bytes::build_statistics(&array, type_.clone()))
} else {
None
};
fixed_len_bytes::array_to_page(&array, options, type_, statistics)
}
DataType::Interval(IntervalUnit::DayTime) => {
let type_ = type_;
let array = array
.as_any()
.downcast_ref::<PrimitiveArray<days_ms>>()
.unwrap();
let mut values = Vec::<u8>::with_capacity(12 * array.len());
array.values().iter().for_each(|x| {
let bytes = &x.to_le_bytes();
values.extend_from_slice(&[0; 4]); // months
values.extend_from_slice(bytes); // days and seconds
});
let array = FixedSizeBinaryArray::new(
DataType::FixedSizeBinary(12),
values.into(),
array.validity().cloned(),
);
let statistics = if options.write_statistics {
Some(fixed_len_bytes::build_statistics(&array, type_.clone()))
} else {
None
};
fixed_len_bytes::array_to_page(&array, options, type_, statistics)
}
DataType::FixedSizeBinary(_) => {
let type_ = type_;
let array = array.as_any().downcast_ref().unwrap();
let statistics = if options.write_statistics {
Some(fixed_len_bytes::build_statistics(array, type_.clone()))
} else {
None
};
fixed_len_bytes::array_to_page(array, options, type_, statistics)
}
DataType::Decimal(precision, _) => {
let type_ = type_;
let precision = *precision;
let array = array
.as_any()
.downcast_ref::<PrimitiveArray<i128>>()
.unwrap();
if precision <= 9 {
let values = array
.values()
.iter()
.map(|x| *x as i32)
.collect::<Vec<_>>()
.into();
let array =
PrimitiveArray::<i32>::new(DataType::Int32, values, array.validity().cloned());
primitive::array_to_page_integer::<i32, i32>(&array, options, type_, encoding)
} else if precision <= 18 {
let values = array
.values()
.iter()
.map(|x| *x as i64)
.collect::<Vec<_>>()
.into();
let array =
PrimitiveArray::<i64>::new(DataType::Int64, values, array.validity().cloned());
primitive::array_to_page_integer::<i64, i64>(&array, options, type_, encoding)
} else {
let size = decimal_length_from_precision(precision);
let statistics = if options.write_statistics {
let stats =
fixed_len_bytes::build_statistics_decimal(array, type_.clone(), size);
Some(stats)
} else {
None
};
let mut values = Vec::<u8>::with_capacity(size * array.len());
array.values().iter().for_each(|x| {
let bytes = &x.to_be_bytes()[16 - size..];
values.extend_from_slice(bytes)
});
let array = FixedSizeBinaryArray::new(
DataType::FixedSizeBinary(size),
values.into(),
array.validity().cloned(),
);
fixed_len_bytes::array_to_page(&array, options, type_, statistics)
}
}
other => Err(Error::NotYetImplemented(format!(
"Writing parquet pages for data type {:?}",
other
))),
}
.map(Page::Data)
}
fn array_to_page_nested(
array: &dyn Array,
type_: ParquetPrimitiveType,
nested: &[Nested],
options: WriteOptions,
_encoding: Encoding,
) -> Result<Page> {
use DataType::*;
match array.data_type().to_logical_type() {
Null => {
let array = Int32Array::new_null(DataType::Int32, array.len());
primitive::nested_array_to_page::<i32, i32>(&array, options, type_, nested)
}
Boolean => {
let array = array.as_any().downcast_ref().unwrap();
boolean::nested_array_to_page(array, options, type_, nested)
}
Utf8 => {
let array = array.as_any().downcast_ref().unwrap();
utf8::nested_array_to_page::<i32>(array, options, type_, nested)
}
LargeUtf8 => {
let array = array.as_any().downcast_ref().unwrap();
utf8::nested_array_to_page::<i64>(array, options, type_, nested)
}
Binary => {
let array = array.as_any().downcast_ref().unwrap();
binary::nested_array_to_page::<i32>(array, options, type_, nested)
}
LargeBinary => {
let array = array.as_any().downcast_ref().unwrap();
binary::nested_array_to_page::<i64>(array, options, type_, nested)
}
UInt8 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<u8, i32>(array, options, type_, nested)
}
UInt16 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<u16, i32>(array, options, type_, nested)
}
UInt32 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<u32, i32>(array, options, type_, nested)
}
UInt64 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<u64, i64>(array, options, type_, nested)
}
Int8 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<i8, i32>(array, options, type_, nested)
}
Int16 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<i16, i32>(array, options, type_, nested)
}
Int32 | Date32 | Time32(_) => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<i32, i32>(array, options, type_, nested)
}
Int64 | Date64 | Time64(_) | Timestamp(_, _) | Duration(_) => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<i64, i64>(array, options, type_, nested)
}
Float32 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<f32, f32>(array, options, type_, nested)
}
Float64 => {
let array = array.as_any().downcast_ref().unwrap();
primitive::nested_array_to_page::<f64, f64>(array, options, type_, nested)
}
other => Err(Error::NotYetImplemented(format!(
"Writing nested parquet pages for data type {:?}",
other
))),
}
.map(Page::Data)
}
sourcepub fn from_values<I: IntoIterator<Item = T>>(iter: I) -> Self
pub fn from_values<I: IntoIterator<Item = T>>(iter: I) -> Self
Creates a (non-null) PrimitiveArray
from an iterator of values.
Implementation
This does not assume that the iterator has a known length.
sourcepub fn from_slice<P: AsRef<[T]>>(slice: P) -> Self
pub fn from_slice<P: AsRef<[T]>>(slice: P) -> Self
Creates a (non-null) PrimitiveArray
from a slice of values.
Implementation
This is essentially a memcopy and is thus O(N)
sourcepub fn from_trusted_len_values_iter<I: TrustedLen<Item = T>>(iter: I) -> Self
pub fn from_trusted_len_values_iter<I: TrustedLen<Item = T>>(iter: I) -> Self
Creates a (non-null) PrimitiveArray
from a TrustedLen
of values.
Implementation
This does not assume that the iterator has a known length.
sourcepub unsafe fn from_trusted_len_values_iter_unchecked<I: Iterator<Item = T>>(
iter: I
) -> Self
pub unsafe fn from_trusted_len_values_iter_unchecked<I: Iterator<Item = T>>(
iter: I
) -> Self
Creates a new PrimitiveArray
from an iterator over values
Safety
The iterator must be TrustedLen
.
I.e. that size_hint().1
correctly reports its length.
sourcepub fn from_trusted_len_iter<I: TrustedLen<Item = Option<T>>>(iter: I) -> Self
pub fn from_trusted_len_iter<I: TrustedLen<Item = Option<T>>>(iter: I) -> Self
Creates a PrimitiveArray
from a TrustedLen
of optional values.
Examples found in repository?
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
pub fn utf8_to_primitive<O: Offset, T>(from: &Utf8Array<O>, to: &DataType) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from
.iter()
.map(|x| x.and_then::<T, _>(|x| lexical_core::parse(x.as_bytes()).ok()));
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
/// Casts a [`Utf8Array`] to a [`PrimitiveArray`] at best-effort using `lexical_core::parse_partial`, making any uncastable value as zero.
pub fn partial_utf8_to_primitive<O: Offset, T>(
from: &Utf8Array<O>,
to: &DataType,
) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from.iter().map(|x| {
x.and_then::<T, _>(|x| lexical_core::parse_partial(x.as_bytes()).ok().map(|x| x.0))
});
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
pub(super) fn utf8_to_primitive_dyn<O: Offset, T>(
from: &dyn Array,
to: &DataType,
options: CastOptions,
) -> Result<Box<dyn Array>>
where
T: NativeType + lexical_core::FromLexical,
{
let from = from.as_any().downcast_ref().unwrap();
if options.partial {
Ok(Box::new(partial_utf8_to_primitive::<O, T>(from, to)))
} else {
Ok(Box::new(utf8_to_primitive::<O, T>(from, to)))
}
}
/// Casts a [`Utf8Array`] to a Date32 primitive, making any uncastable value a Null.
pub fn utf8_to_date32<O: Offset>(from: &Utf8Array<O>) -> PrimitiveArray<i32> {
let iter = from.iter().map(|x| {
x.and_then(|x| {
x.parse::<chrono::NaiveDate>()
.ok()
.map(|x| x.num_days_from_ce() - EPOCH_DAYS_FROM_CE)
})
});
PrimitiveArray::<i32>::from_trusted_len_iter(iter).to(DataType::Date32)
}
pub(super) fn utf8_to_date32_dyn<O: Offset>(from: &dyn Array) -> Result<Box<dyn Array>> {
let from = from.as_any().downcast_ref().unwrap();
Ok(Box::new(utf8_to_date32::<O>(from)))
}
/// Casts a [`Utf8Array`] to a Date64 primitive, making any uncastable value a Null.
pub fn utf8_to_date64<O: Offset>(from: &Utf8Array<O>) -> PrimitiveArray<i64> {
let iter = from.iter().map(|x| {
x.and_then(|x| {
x.parse::<chrono::NaiveDate>()
.ok()
.map(|x| (x.num_days_from_ce() - EPOCH_DAYS_FROM_CE) as i64 * 86400000)
})
});
PrimitiveArray::from_trusted_len_iter(iter).to(DataType::Date64)
}
More examples
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
pub fn partial_binary_to_primitive<O: Offset, T>(
from: &BinaryArray<O>,
to: &DataType,
) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from
.iter()
.map(|x| x.and_then::<T, _>(|x| lexical_core::parse_partial(x).ok().map(|x| x.0)));
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
/// Casts a [`BinaryArray`] to a [`PrimitiveArray`], making any uncastable value a Null.
pub fn binary_to_primitive<O: Offset, T>(from: &BinaryArray<O>, to: &DataType) -> PrimitiveArray<T>
where
T: NativeType + lexical_core::FromLexical,
{
let iter = from
.iter()
.map(|x| x.and_then::<T, _>(|x| lexical_core::parse(x).ok()));
PrimitiveArray::<T>::from_trusted_len_iter(iter).to(to.clone())
}
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
pub fn primitive_to_primitive<I, O>(
from: &PrimitiveArray<I>,
to_type: &DataType,
) -> PrimitiveArray<O>
where
I: NativeType + num_traits::NumCast,
O: NativeType + num_traits::NumCast,
{
let iter = from
.iter()
.map(|v| v.and_then(|x| num_traits::cast::cast::<I, O>(*x)));
PrimitiveArray::<O>::from_trusted_len_iter(iter).to(to_type.clone())
}
/// Returns a [`PrimitiveArray<i128>`] with the casted values. Values are `None` on overflow
pub fn integer_to_decimal<T: NativeType + AsPrimitive<i128>>(
from: &PrimitiveArray<T>,
to_precision: usize,
to_scale: usize,
) -> PrimitiveArray<i128> {
let multiplier = 10_i128.pow(to_scale as u32);
let min_for_precision = 9_i128
.saturating_pow(1 + to_precision as u32)
.saturating_neg();
let max_for_precision = 9_i128.saturating_pow(1 + to_precision as u32);
let values = from.iter().map(|x| {
x.and_then(|x| {
x.as_().checked_mul(multiplier).and_then(|x| {
if x > max_for_precision || x < min_for_precision {
None
} else {
Some(x)
}
})
})
});
PrimitiveArray::<i128>::from_trusted_len_iter(values)
.to(DataType::Decimal(to_precision, to_scale))
}
pub(super) fn integer_to_decimal_dyn<T>(
from: &dyn Array,
precision: usize,
scale: usize,
) -> Result<Box<dyn Array>>
where
T: NativeType + AsPrimitive<i128>,
{
let from = from.as_any().downcast_ref().unwrap();
Ok(Box::new(integer_to_decimal::<T>(from, precision, scale)))
}
/// Returns a [`PrimitiveArray<i128>`] with the casted values. Values are `None` on overflow
pub fn float_to_decimal<T>(
from: &PrimitiveArray<T>,
to_precision: usize,
to_scale: usize,
) -> PrimitiveArray<i128>
where
T: NativeType + Float + ToPrimitive,
f64: AsPrimitive<T>,
{
// 1.2 => 12
let multiplier: T = (10_f64).powi(to_scale as i32).as_();
let min_for_precision = 9_i128
.saturating_pow(1 + to_precision as u32)
.saturating_neg();
let max_for_precision = 9_i128.saturating_pow(1 + to_precision as u32);
let values = from.iter().map(|x| {
x.and_then(|x| {
let x = (*x * multiplier).to_i128().unwrap();
if x > max_for_precision || x < min_for_precision {
None
} else {
Some(x)
}
})
});
PrimitiveArray::<i128>::from_trusted_len_iter(values)
.to(DataType::Decimal(to_precision, to_scale))
}
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
fn utf8_to_timestamp_ns_impl<O: Offset, T: chrono::TimeZone>(
array: &Utf8Array<O>,
fmt: &str,
timezone: String,
tz: T,
) -> PrimitiveArray<i64> {
let iter = array
.iter()
.map(|x| x.and_then(|x| utf8_to_timestamp_ns_scalar(x, fmt, &tz)));
PrimitiveArray::from_trusted_len_iter(iter)
.to(DataType::Timestamp(TimeUnit::Nanosecond, Some(timezone)))
}
/// Parses `value` to a [`chrono_tz::Tz`] with the Arrow's definition of timestamp with a timezone.
#[cfg(feature = "chrono-tz")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-tz")))]
pub fn parse_offset_tz(timezone: &str) -> Result<chrono_tz::Tz> {
timezone.parse::<chrono_tz::Tz>().map_err(|_| {
Error::InvalidArgumentError(format!("timezone \"{}\" cannot be parsed", timezone))
})
}
#[cfg(feature = "chrono-tz")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-tz")))]
fn chrono_tz_utf_to_timestamp_ns<O: Offset>(
array: &Utf8Array<O>,
fmt: &str,
timezone: String,
) -> Result<PrimitiveArray<i64>> {
let tz = parse_offset_tz(&timezone)?;
Ok(utf8_to_timestamp_ns_impl(array, fmt, timezone, tz))
}
#[cfg(not(feature = "chrono-tz"))]
fn chrono_tz_utf_to_timestamp_ns<O: Offset>(
_: &Utf8Array<O>,
_: &str,
timezone: String,
) -> Result<PrimitiveArray<i64>> {
Err(Error::InvalidArgumentError(format!(
"timezone \"{}\" cannot be parsed (feature chrono-tz is not active)",
timezone
)))
}
/// Parses a [`Utf8Array`] to a timeozone-aware timestamp, i.e. [`PrimitiveArray<i64>`] with type `Timestamp(Nanosecond, Some(timezone))`.
/// # Implementation
/// * parsed values with timezone other than `timezone` are converted to `timezone`.
/// * parsed values without timezone are null. Use [`utf8_to_naive_timestamp_ns`] to parse naive timezones.
/// * Null elements remain null; non-parsable elements are null.
/// The feature `"chrono-tz"` enables IANA and zoneinfo formats for `timezone`.
/// # Error
/// This function errors iff `timezone` is not parsable to an offset.
pub fn utf8_to_timestamp_ns<O: Offset>(
array: &Utf8Array<O>,
fmt: &str,
timezone: String,
) -> Result<PrimitiveArray<i64>> {
let tz = parse_offset(timezone.as_str());
if let Ok(tz) = tz {
Ok(utf8_to_timestamp_ns_impl(array, fmt, timezone, tz))
} else {
chrono_tz_utf_to_timestamp_ns(array, fmt, timezone)
}
}
/// Parses a [`Utf8Array`] to naive timestamp, i.e.
/// [`PrimitiveArray<i64>`] with type `Timestamp(Nanosecond, None)`.
/// Timezones are ignored.
/// Null elements remain null; non-parsable elements are set to null.
pub fn utf8_to_naive_timestamp_ns<O: Offset>(
array: &Utf8Array<O>,
fmt: &str,
) -> PrimitiveArray<i64> {
let iter = array
.iter()
.map(|x| x.and_then(|x| utf8_to_naive_timestamp_ns_scalar(x, fmt)));
PrimitiveArray::from_trusted_len_iter(iter).to(DataType::Timestamp(TimeUnit::Nanosecond, None))
}
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
fn deserialize_primitive<T, B: ByteRecordGeneric, F>(
rows: &[B],
column: usize,
datatype: DataType,
op: F,
) -> Box<dyn Array>
where
T: NativeType + lexical_core::FromLexical,
F: Fn(&[u8]) -> Option<T>,
{
let iter = rows.iter().map(|row| match row.get(column) {
Some(bytes) => {
if bytes.is_empty() {
return None;
}
op(bytes)
}
None => None,
});
Box::new(PrimitiveArray::<T>::from_trusted_len_iter(iter).to(datatype))
}
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
pub fn deserialize(indexes: &[PageIndex<bool>]) -> ColumnPageStatistics {
ColumnPageStatistics {
min: Box::new(BooleanArray::from_trusted_len_iter(
indexes.iter().map(|index| index.min),
)),
max: Box::new(BooleanArray::from_trusted_len_iter(
indexes.iter().map(|index| index.max),
)),
null_count: PrimitiveArray::from_trusted_len_iter(
indexes
.iter()
.map(|index| index.null_count.map(|x| x as u64)),
),
}
}
sourcepub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = Option<T>>>(
iter: I
) -> Self
pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = Option<T>>>(
iter: I
) -> Self
Creates a PrimitiveArray
from an iterator of optional values.
Safety
The iterator must be TrustedLen
.
I.e. that size_hint().1
correctly reports its length.
sourcepub fn boxed(self) -> Box<dyn Array>
pub fn boxed(self) -> Box<dyn Array>
Boxes self into a Box<dyn Array>
.
Examples found in repository?
More examples
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
fn binary_dyn<T: NativeType, F: Fn(&PrimitiveArray<T>, &PrimitiveArray<T>) -> PrimitiveArray<T>>(
lhs: &dyn Array,
rhs: &dyn Array,
op: F,
) -> Box<dyn Array> {
let lhs = lhs.as_any().downcast_ref().unwrap();
let rhs = rhs.as_any().downcast_ref().unwrap();
op(lhs, rhs).boxed()
}
// Macro to create a `match` statement with dynamic dispatch to functions based on
// the array's logical types
macro_rules! arith {
($lhs:expr, $rhs:expr, $op:tt $(, decimal = $op_decimal:tt )? $(, duration = $op_duration:tt )? $(, interval = $op_interval:tt )? $(, timestamp = $op_timestamp:tt )?) => {{
let lhs = $lhs;
let rhs = $rhs;
use DataType::*;
match (lhs.data_type(), rhs.data_type()) {
(Int8, Int8) => binary_dyn::<i8, _>(lhs, rhs, basic::$op),
(Int16, Int16) => binary_dyn::<i16, _>(lhs, rhs, basic::$op),
(Int32, Int32) => binary_dyn::<i32, _>(lhs, rhs, basic::$op),
(Int64, Int64) | (Duration(_), Duration(_)) => {
binary_dyn::<i64, _>(lhs, rhs, basic::$op)
}
(UInt8, UInt8) => binary_dyn::<u8, _>(lhs, rhs, basic::$op),
(UInt16, UInt16) => binary_dyn::<u16, _>(lhs, rhs, basic::$op),
(UInt32, UInt32) => binary_dyn::<u32, _>(lhs, rhs, basic::$op),
(UInt64, UInt64) => binary_dyn::<u64, _>(lhs, rhs, basic::$op),
(Float32, Float32) => binary_dyn::<f32, _>(lhs, rhs, basic::$op),
(Float64, Float64) => binary_dyn::<f64, _>(lhs, rhs, basic::$op),
$ (
(Decimal(_, _), Decimal(_, _)) => {
let lhs = lhs.as_any().downcast_ref().unwrap();
let rhs = rhs.as_any().downcast_ref().unwrap();
Box::new(decimal::$op_decimal(lhs, rhs)) as Box<dyn Array>
}
)?
$ (
(Time32(TimeUnit::Second), Duration(_))
| (Time32(TimeUnit::Millisecond), Duration(_))
| (Date32, Duration(_)) => {
let lhs = lhs.as_any().downcast_ref().unwrap();
let rhs = rhs.as_any().downcast_ref().unwrap();
Box::new(time::$op_duration::<i32>(lhs, rhs)) as Box<dyn Array>
}
(Time64(TimeUnit::Microsecond), Duration(_))
| (Time64(TimeUnit::Nanosecond), Duration(_))
| (Date64, Duration(_))
| (Timestamp(_, _), Duration(_)) => {
let lhs = lhs.as_any().downcast_ref().unwrap();
let rhs = rhs.as_any().downcast_ref().unwrap();
Box::new(time::$op_duration::<i64>(lhs, rhs)) as Box<dyn Array>
}
)?
$ (
(Timestamp(_, _), Interval(IntervalUnit::MonthDayNano)) => {
let lhs = lhs.as_any().downcast_ref().unwrap();
let rhs = rhs.as_any().downcast_ref().unwrap();
time::$op_interval(lhs, rhs).map(|x| Box::new(x) as Box<dyn Array>).unwrap()
}
)?
$ (
(Timestamp(_, None), Timestamp(_, None)) => {
let lhs = lhs.as_any().downcast_ref().unwrap();
let rhs = rhs.as_any().downcast_ref().unwrap();
time::$op_timestamp(lhs, rhs).map(|x| Box::new(x) as Box<dyn Array>).unwrap()
}
)?
_ => todo!(
"Addition of {:?} with {:?} is not supported",
lhs.data_type(),
rhs.data_type()
),
}
}};
}
fn binary_scalar<T: NativeType, F: Fn(&PrimitiveArray<T>, &T) -> PrimitiveArray<T>>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveScalar<T>,
op: F,
) -> PrimitiveArray<T> {
let rhs = if let Some(rhs) = *rhs.value() {
rhs
} else {
return PrimitiveArray::<T>::new_null(lhs.data_type().clone(), lhs.len());
};
op(lhs, &rhs)
}
fn binary_scalar_dyn<T: NativeType, F: Fn(&PrimitiveArray<T>, &T) -> PrimitiveArray<T>>(
lhs: &dyn Array,
rhs: &dyn Scalar,
op: F,
) -> Box<dyn Array> {
let lhs = lhs.as_any().downcast_ref().unwrap();
let rhs = rhs.as_any().downcast_ref().unwrap();
binary_scalar(lhs, rhs, op).boxed()
}
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
pub fn deserialize(data_type: DataType, column: &Column) -> Result<Box<dyn Array>, Error> {
match data_type {
DataType::Boolean => deserialize_bool(data_type, column).map(|x| x.boxed()),
DataType::Int8 => deserialize_int::<i8>(data_type, column).map(|x| x.boxed()),
DataType::Int16 => deserialize_int::<i16>(data_type, column).map(|x| x.boxed()),
DataType::Int32 => deserialize_int::<i32>(data_type, column).map(|x| x.boxed()),
DataType::Int64 => deserialize_i64(data_type, column).map(|x| x.boxed()),
DataType::Float32 => deserialize_float::<f32>(data_type, column).map(|x| x.boxed()),
DataType::Float64 => deserialize_float::<f64>(data_type, column).map(|x| x.boxed()),
DataType::Utf8 => deserialize_utf8::<i32>(data_type, column).map(|x| x.boxed()),
DataType::LargeUtf8 => deserialize_utf8::<i64>(data_type, column).map(|x| x.boxed()),
DataType::Binary => deserialize_binary::<i32>(data_type, column).map(|x| x.boxed()),
DataType::LargeBinary => deserialize_binary::<i64>(data_type, column).map(|x| x.boxed()),
dt => Err(Error::nyi(format!("Deserializing {dt:?} from ORC"))),
}
}
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
fn from(mut s: MutableStatistics) -> Self {
let null_count = if let PhysicalType::Struct = s.null_count.data_type().to_physical_type() {
s.null_count
.as_box()
.as_any()
.downcast_ref::<StructArray>()
.unwrap()
.clone()
.boxed()
} else if let PhysicalType::Map = s.null_count.data_type().to_physical_type() {
s.null_count
.as_box()
.as_any()
.downcast_ref::<MapArray>()
.unwrap()
.clone()
.boxed()
} else if let PhysicalType::List = s.null_count.data_type().to_physical_type() {
s.null_count
.as_box()
.as_any()
.downcast_ref::<ListArray<i32>>()
.unwrap()
.clone()
.boxed()
} else if let PhysicalType::LargeList = s.null_count.data_type().to_physical_type() {
s.null_count
.as_box()
.as_any()
.downcast_ref::<ListArray<i64>>()
.unwrap()
.clone()
.boxed()
} else {
s.null_count
.as_box()
.as_any()
.downcast_ref::<UInt64Array>()
.unwrap()
.clone()
.boxed()
};
let distinct_count = if let PhysicalType::Struct =
s.distinct_count.data_type().to_physical_type()
{
s.distinct_count
.as_box()
.as_any()
.downcast_ref::<StructArray>()
.unwrap()
.clone()
.boxed()
} else if let PhysicalType::Map = s.distinct_count.data_type().to_physical_type() {
s.distinct_count
.as_box()
.as_any()
.downcast_ref::<MapArray>()
.unwrap()
.clone()
.boxed()
} else if let PhysicalType::List = s.distinct_count.data_type().to_physical_type() {
s.distinct_count
.as_box()
.as_any()
.downcast_ref::<ListArray<i32>>()
.unwrap()
.clone()
.boxed()
} else if let PhysicalType::LargeList = s.distinct_count.data_type().to_physical_type() {
s.distinct_count
.as_box()
.as_any()
.downcast_ref::<ListArray<i64>>()
.unwrap()
.clone()
.boxed()
} else {
s.distinct_count
.as_box()
.as_any()
.downcast_ref::<UInt64Array>()
.unwrap()
.clone()
.boxed()
};
Self {
null_count,
distinct_count,
min_value: s.min_value.as_box(),
max_value: s.max_value.as_box(),
}
}
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
pub fn page_iter_to_arrays<'a, I: Pages + 'a>(
pages: I,
type_: &PrimitiveType,
data_type: DataType,
chunk_size: Option<usize>,
num_rows: usize,
) -> Result<ArrayIter<'a>> {
use DataType::*;
let physical_type = &type_.physical_type;
let logical_type = &type_.logical_type;
Ok(match data_type.to_logical_type() {
Null => null::iter_to_arrays(pages, data_type, chunk_size, num_rows),
Boolean => dyn_iter(boolean::Iter::new(pages, data_type, chunk_size, num_rows)),
UInt8 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as u8,
))),
UInt16 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as u16,
))),
UInt32 => match physical_type {
PhysicalType::Int32 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as u32,
))),
// some implementations of parquet write arrow's u32 into i64.
PhysicalType::Int64 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x as u32,
))),
other => {
return Err(Error::NotYetImplemented(format!(
"Reading uin32 from {:?}-encoded parquet still not implemented",
other
)))
}
},
Int8 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as i8,
))),
Int16 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as i16,
))),
Int32 | Date32 | Time32(_) => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x,
))),
Timestamp(time_unit, _) => {
let time_unit = *time_unit;
return timestamp(
pages,
physical_type,
logical_type,
data_type,
num_rows,
chunk_size,
time_unit,
);
}
FixedSizeBinary(_) => dyn_iter(fixed_size_binary::Iter::new(
pages, data_type, num_rows, chunk_size,
)),
Interval(IntervalUnit::YearMonth) => {
let n = 12;
let pages = fixed_size_binary::Iter::new(
pages,
DataType::FixedSizeBinary(n),
num_rows,
chunk_size,
);
let pages = pages.map(move |maybe_array| {
let array = maybe_array?;
let values = array
.values()
.chunks_exact(n)
.map(|value: &[u8]| i32::from_le_bytes(value[..4].try_into().unwrap()))
.collect::<Vec<_>>();
let validity = array.validity().cloned();
PrimitiveArray::<i32>::try_new(data_type.clone(), values.into(), validity)
});
let arrays = pages.map(|x| x.map(|x| x.boxed()));
Box::new(arrays) as _
}
Interval(IntervalUnit::DayTime) => {
let n = 12;
let pages = fixed_size_binary::Iter::new(
pages,
DataType::FixedSizeBinary(n),
num_rows,
chunk_size,
);
let pages = pages.map(move |maybe_array| {
let array = maybe_array?;
let values = array
.values()
.chunks_exact(n)
.map(super::super::convert_days_ms)
.collect::<Vec<_>>();
let validity = array.validity().cloned();
PrimitiveArray::<days_ms>::try_new(data_type.clone(), values.into(), validity)
});
let arrays = pages.map(|x| x.map(|x| x.boxed()));
Box::new(arrays) as _
}
Decimal(_, _) => match physical_type {
PhysicalType::Int32 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i32| x as i128,
))),
PhysicalType::Int64 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x as i128,
))),
PhysicalType::FixedLenByteArray(n) if *n > 16 => {
return Err(Error::NotYetImplemented(format!(
"Can't decode Decimal128 type from Fixed Size Byte Array of len {:?}",
n
)))
}
PhysicalType::FixedLenByteArray(n) => {
let n = *n;
let pages = fixed_size_binary::Iter::new(
pages,
DataType::FixedSizeBinary(n),
num_rows,
chunk_size,
);
let pages = pages.map(move |maybe_array| {
let array = maybe_array?;
let values = array
.values()
.chunks_exact(n)
.map(|value: &[u8]| super::super::convert_i128(value, n))
.collect::<Vec<_>>();
let validity = array.validity().cloned();
PrimitiveArray::<i128>::try_new(data_type.clone(), values.into(), validity)
});
let arrays = pages.map(|x| x.map(|x| x.boxed()));
Box::new(arrays) as _
}
_ => unreachable!(),
},
// INT64
Int64 | Date64 | Time64(_) | Duration(_) => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x,
))),
UInt64 => dyn_iter(iden(primitive::IntegerIter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: i64| x as u64,
))),
Float32 => dyn_iter(iden(primitive::Iter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: f32| x,
))),
Float64 => dyn_iter(iden(primitive::Iter::new(
pages,
data_type,
num_rows,
chunk_size,
|x: f64| x,
))),
Binary => dyn_iter(binary::Iter::<i32, BinaryArray<i32>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
LargeBinary => dyn_iter(binary::Iter::<i64, BinaryArray<i64>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
Utf8 => dyn_iter(binary::Iter::<i32, Utf8Array<i32>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
LargeUtf8 => dyn_iter(binary::Iter::<i64, Utf8Array<i64>, _>::new(
pages, data_type, chunk_size, num_rows,
)),
Dictionary(key_type, _, _) => {
return match_integer_type!(key_type, |$K| {
dict_read::<$K, _>(pages, physical_type, logical_type, data_type, num_rows, chunk_size)
})
}
other => {
return Err(Error::NotYetImplemented(format!(
"Reading {:?} from parquet still not implemented",
other
)))
}
})
}
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
pub fn cast(array: &dyn Array, to_type: &DataType, options: CastOptions) -> Result<Box<dyn Array>> {
use DataType::*;
let from_type = array.data_type();
// clone array if types are the same
if from_type == to_type {
return Ok(clone(array));
}
let as_options = options.with_wrapped(true);
match (from_type, to_type) {
(Null, _) | (_, Null) => Ok(new_null_array(to_type.clone(), array.len())),
(Struct(_), _) => Err(Error::NotYetImplemented(
"Cannot cast from struct to other types".to_string(),
)),
(_, Struct(_)) => Err(Error::NotYetImplemented(
"Cannot cast to struct from other types".to_string(),
)),
(List(_), FixedSizeList(inner, size)) => cast_list_to_fixed_size_list(
array.as_any().downcast_ref().unwrap(),
inner.as_ref(),
*size,
options,
)
.map(|x| x.boxed()),
(FixedSizeList(_, _), List(_)) => {
cast_fixed_size_list_to_list(array.as_any().downcast_ref().unwrap(), to_type, options)
.map(|x| x.boxed())
}
(List(_), List(_)) => {
cast_list::<i32>(array.as_any().downcast_ref().unwrap(), to_type, options)
.map(|x| x.boxed())
}
(LargeList(_), LargeList(_)) => {
cast_list::<i64>(array.as_any().downcast_ref().unwrap(), to_type, options)
.map(|x| x.boxed())
}
(List(lhs), LargeList(rhs)) if lhs == rhs => {
Ok(cast_list_to_large_list(array.as_any().downcast_ref().unwrap(), to_type).boxed())
}
(LargeList(lhs), List(rhs)) if lhs == rhs => {
Ok(cast_large_to_list(array.as_any().downcast_ref().unwrap(), to_type).boxed())
}
(_, List(to)) => {
// cast primitive to list's primitive
let values = cast(array, &to.data_type, options)?;
// create offsets, where if array.len() = 2, we have [0,1,2]
let offsets = (0..=array.len() as i32).collect::<Vec<_>>();
// Safety: offsets _are_ monotonically increasing
let offsets = unsafe { Offsets::new_unchecked(offsets) };
let list_array = ListArray::<i32>::new(to_type.clone(), offsets.into(), values, None);
Ok(Box::new(list_array))
}
(Dictionary(index_type, ..), _) => match_integer_type!(index_type, |$T| {
dictionary_cast_dyn::<$T>(array, to_type, options)
}),
(_, Dictionary(index_type, value_type, _)) => match_integer_type!(index_type, |$T| {
cast_to_dictionary::<$T>(array, value_type, options)
}),
(_, Boolean) => match from_type {
UInt8 => primitive_to_boolean_dyn::<u8>(array, to_type.clone()),
UInt16 => primitive_to_boolean_dyn::<u16>(array, to_type.clone()),
UInt32 => primitive_to_boolean_dyn::<u32>(array, to_type.clone()),
UInt64 => primitive_to_boolean_dyn::<u64>(array, to_type.clone()),
Int8 => primitive_to_boolean_dyn::<i8>(array, to_type.clone()),
Int16 => primitive_to_boolean_dyn::<i16>(array, to_type.clone()),
Int32 => primitive_to_boolean_dyn::<i32>(array, to_type.clone()),
Int64 => primitive_to_boolean_dyn::<i64>(array, to_type.clone()),
Float32 => primitive_to_boolean_dyn::<f32>(array, to_type.clone()),
Float64 => primitive_to_boolean_dyn::<f64>(array, to_type.clone()),
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(Boolean, _) => match to_type {
UInt8 => boolean_to_primitive_dyn::<u8>(array),
UInt16 => boolean_to_primitive_dyn::<u16>(array),
UInt32 => boolean_to_primitive_dyn::<u32>(array),
UInt64 => boolean_to_primitive_dyn::<u64>(array),
Int8 => boolean_to_primitive_dyn::<i8>(array),
Int16 => boolean_to_primitive_dyn::<i16>(array),
Int32 => boolean_to_primitive_dyn::<i32>(array),
Int64 => boolean_to_primitive_dyn::<i64>(array),
Float32 => boolean_to_primitive_dyn::<f32>(array),
Float64 => boolean_to_primitive_dyn::<f64>(array),
Utf8 => boolean_to_utf8_dyn::<i32>(array),
LargeUtf8 => boolean_to_utf8_dyn::<i64>(array),
Binary => boolean_to_binary_dyn::<i32>(array),
LargeBinary => boolean_to_binary_dyn::<i64>(array),
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(Utf8, _) => match to_type {
UInt8 => utf8_to_primitive_dyn::<i32, u8>(array, to_type, options),
UInt16 => utf8_to_primitive_dyn::<i32, u16>(array, to_type, options),
UInt32 => utf8_to_primitive_dyn::<i32, u32>(array, to_type, options),
UInt64 => utf8_to_primitive_dyn::<i32, u64>(array, to_type, options),
Int8 => utf8_to_primitive_dyn::<i32, i8>(array, to_type, options),
Int16 => utf8_to_primitive_dyn::<i32, i16>(array, to_type, options),
Int32 => utf8_to_primitive_dyn::<i32, i32>(array, to_type, options),
Int64 => utf8_to_primitive_dyn::<i32, i64>(array, to_type, options),
Float32 => utf8_to_primitive_dyn::<i32, f32>(array, to_type, options),
Float64 => utf8_to_primitive_dyn::<i32, f64>(array, to_type, options),
Date32 => utf8_to_date32_dyn::<i32>(array),
Date64 => utf8_to_date64_dyn::<i32>(array),
LargeUtf8 => Ok(Box::new(utf8_to_large_utf8(
array.as_any().downcast_ref().unwrap(),
))),
Binary => Ok(utf8_to_binary::<i32>(
array.as_any().downcast_ref().unwrap(),
to_type.clone(),
)
.boxed()),
Timestamp(TimeUnit::Nanosecond, None) => utf8_to_naive_timestamp_ns_dyn::<i32>(array),
Timestamp(TimeUnit::Nanosecond, Some(tz)) => {
utf8_to_timestamp_ns_dyn::<i32>(array, tz.clone())
}
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(LargeUtf8, _) => match to_type {
UInt8 => utf8_to_primitive_dyn::<i64, u8>(array, to_type, options),
UInt16 => utf8_to_primitive_dyn::<i64, u16>(array, to_type, options),
UInt32 => utf8_to_primitive_dyn::<i64, u32>(array, to_type, options),
UInt64 => utf8_to_primitive_dyn::<i64, u64>(array, to_type, options),
Int8 => utf8_to_primitive_dyn::<i64, i8>(array, to_type, options),
Int16 => utf8_to_primitive_dyn::<i64, i16>(array, to_type, options),
Int32 => utf8_to_primitive_dyn::<i64, i32>(array, to_type, options),
Int64 => utf8_to_primitive_dyn::<i64, i64>(array, to_type, options),
Float32 => utf8_to_primitive_dyn::<i64, f32>(array, to_type, options),
Float64 => utf8_to_primitive_dyn::<i64, f64>(array, to_type, options),
Date32 => utf8_to_date32_dyn::<i64>(array),
Date64 => utf8_to_date64_dyn::<i64>(array),
Utf8 => utf8_large_to_utf8(array.as_any().downcast_ref().unwrap()).map(|x| x.boxed()),
LargeBinary => Ok(utf8_to_binary::<i64>(
array.as_any().downcast_ref().unwrap(),
to_type.clone(),
)
.boxed()),
Timestamp(TimeUnit::Nanosecond, None) => utf8_to_naive_timestamp_ns_dyn::<i64>(array),
Timestamp(TimeUnit::Nanosecond, Some(tz)) => {
utf8_to_timestamp_ns_dyn::<i64>(array, tz.clone())
}
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(_, Utf8) => match from_type {
UInt8 => primitive_to_utf8_dyn::<u8, i32>(array),
UInt16 => primitive_to_utf8_dyn::<u16, i32>(array),
UInt32 => primitive_to_utf8_dyn::<u32, i32>(array),
UInt64 => primitive_to_utf8_dyn::<u64, i32>(array),
Int8 => primitive_to_utf8_dyn::<i8, i32>(array),
Int16 => primitive_to_utf8_dyn::<i16, i32>(array),
Int32 => primitive_to_utf8_dyn::<i32, i32>(array),
Int64 => primitive_to_utf8_dyn::<i64, i32>(array),
Float32 => primitive_to_utf8_dyn::<f32, i32>(array),
Float64 => primitive_to_utf8_dyn::<f64, i32>(array),
Binary => {
let array = array.as_any().downcast_ref::<BinaryArray<i32>>().unwrap();
// perf todo: the offsets are equal; we can speed-up this
let iter = array
.iter()
.map(|x| x.and_then(|x| simdutf8::basic::from_utf8(x).ok()));
let array = Utf8Array::<i32>::from_trusted_len_iter(iter);
Ok(Box::new(array))
}
Timestamp(from_unit, Some(tz)) => {
let from = array.as_any().downcast_ref().unwrap();
Ok(Box::new(timestamp_to_utf8::<i32>(from, *from_unit, tz)?))
}
Timestamp(from_unit, None) => {
let from = array.as_any().downcast_ref().unwrap();
Ok(Box::new(naive_timestamp_to_utf8::<i32>(from, *from_unit)))
}
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(_, LargeUtf8) => match from_type {
UInt8 => primitive_to_utf8_dyn::<u8, i64>(array),
UInt16 => primitive_to_utf8_dyn::<u16, i64>(array),
UInt32 => primitive_to_utf8_dyn::<u32, i64>(array),
UInt64 => primitive_to_utf8_dyn::<u64, i64>(array),
Int8 => primitive_to_utf8_dyn::<i8, i64>(array),
Int16 => primitive_to_utf8_dyn::<i16, i64>(array),
Int32 => primitive_to_utf8_dyn::<i32, i64>(array),
Int64 => primitive_to_utf8_dyn::<i64, i64>(array),
Float32 => primitive_to_utf8_dyn::<f32, i64>(array),
Float64 => primitive_to_utf8_dyn::<f64, i64>(array),
Binary => binary_to_large_utf8(array.as_any().downcast_ref().unwrap(), to_type.clone())
.map(|x| x.boxed()),
LargeBinary => {
binary_to_utf8::<i64>(array.as_any().downcast_ref().unwrap(), to_type.clone())
.map(|x| x.boxed())
}
Timestamp(from_unit, Some(tz)) => {
let from = array.as_any().downcast_ref().unwrap();
Ok(Box::new(timestamp_to_utf8::<i64>(from, *from_unit, tz)?))
}
Timestamp(from_unit, None) => {
let from = array.as_any().downcast_ref().unwrap();
Ok(Box::new(naive_timestamp_to_utf8::<i64>(from, *from_unit)))
}
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(Binary, _) => match to_type {
UInt8 => binary_to_primitive_dyn::<i32, u8>(array, to_type, options),
UInt16 => binary_to_primitive_dyn::<i32, u16>(array, to_type, options),
UInt32 => binary_to_primitive_dyn::<i32, u32>(array, to_type, options),
UInt64 => binary_to_primitive_dyn::<i32, u64>(array, to_type, options),
Int8 => binary_to_primitive_dyn::<i32, i8>(array, to_type, options),
Int16 => binary_to_primitive_dyn::<i32, i16>(array, to_type, options),
Int32 => binary_to_primitive_dyn::<i32, i32>(array, to_type, options),
Int64 => binary_to_primitive_dyn::<i32, i64>(array, to_type, options),
Float32 => binary_to_primitive_dyn::<i32, f32>(array, to_type, options),
Float64 => binary_to_primitive_dyn::<i32, f64>(array, to_type, options),
LargeBinary => Ok(Box::new(binary_to_large_binary(
array.as_any().downcast_ref().unwrap(),
to_type.clone(),
))),
Utf8 => binary_to_utf8::<i32>(array.as_any().downcast_ref().unwrap(), to_type.clone())
.map(|x| x.boxed()),
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(LargeBinary, _) => match to_type {
UInt8 => binary_to_primitive_dyn::<i64, u8>(array, to_type, options),
UInt16 => binary_to_primitive_dyn::<i64, u16>(array, to_type, options),
UInt32 => binary_to_primitive_dyn::<i64, u32>(array, to_type, options),
UInt64 => binary_to_primitive_dyn::<i64, u64>(array, to_type, options),
Int8 => binary_to_primitive_dyn::<i64, i8>(array, to_type, options),
Int16 => binary_to_primitive_dyn::<i64, i16>(array, to_type, options),
Int32 => binary_to_primitive_dyn::<i64, i32>(array, to_type, options),
Int64 => binary_to_primitive_dyn::<i64, i64>(array, to_type, options),
Float32 => binary_to_primitive_dyn::<i64, f32>(array, to_type, options),
Float64 => binary_to_primitive_dyn::<i64, f64>(array, to_type, options),
Binary => {
binary_large_to_binary(array.as_any().downcast_ref().unwrap(), to_type.clone())
.map(|x| x.boxed())
}
LargeUtf8 => {
binary_to_utf8::<i64>(array.as_any().downcast_ref().unwrap(), to_type.clone())
.map(|x| x.boxed())
}
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(_, Binary) => match from_type {
UInt8 => primitive_to_binary_dyn::<u8, i32>(array),
UInt16 => primitive_to_binary_dyn::<u16, i32>(array),
UInt32 => primitive_to_binary_dyn::<u32, i32>(array),
UInt64 => primitive_to_binary_dyn::<u64, i32>(array),
Int8 => primitive_to_binary_dyn::<i8, i32>(array),
Int16 => primitive_to_binary_dyn::<i16, i32>(array),
Int32 => primitive_to_binary_dyn::<i32, i32>(array),
Int64 => primitive_to_binary_dyn::<i64, i32>(array),
Float32 => primitive_to_binary_dyn::<f32, i32>(array),
Float64 => primitive_to_binary_dyn::<f64, i32>(array),
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
(_, LargeBinary) => match from_type {
UInt8 => primitive_to_binary_dyn::<u8, i64>(array),
UInt16 => primitive_to_binary_dyn::<u16, i64>(array),
UInt32 => primitive_to_binary_dyn::<u32, i64>(array),
UInt64 => primitive_to_binary_dyn::<u64, i64>(array),
Int8 => primitive_to_binary_dyn::<i8, i64>(array),
Int16 => primitive_to_binary_dyn::<i16, i64>(array),
Int32 => primitive_to_binary_dyn::<i32, i64>(array),
Int64 => primitive_to_binary_dyn::<i64, i64>(array),
Float32 => primitive_to_binary_dyn::<f32, i64>(array),
Float64 => primitive_to_binary_dyn::<f64, i64>(array),
_ => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
},
// start numeric casts
(UInt8, UInt16) => primitive_to_primitive_dyn::<u8, u16>(array, to_type, as_options),
(UInt8, UInt32) => primitive_to_primitive_dyn::<u8, u32>(array, to_type, as_options),
(UInt8, UInt64) => primitive_to_primitive_dyn::<u8, u64>(array, to_type, as_options),
(UInt8, Int8) => primitive_to_primitive_dyn::<u8, i8>(array, to_type, options),
(UInt8, Int16) => primitive_to_primitive_dyn::<u8, i16>(array, to_type, options),
(UInt8, Int32) => primitive_to_primitive_dyn::<u8, i32>(array, to_type, options),
(UInt8, Int64) => primitive_to_primitive_dyn::<u8, i64>(array, to_type, options),
(UInt8, Float32) => primitive_to_primitive_dyn::<u8, f32>(array, to_type, as_options),
(UInt8, Float64) => primitive_to_primitive_dyn::<u8, f64>(array, to_type, as_options),
(UInt8, Decimal(p, s)) => integer_to_decimal_dyn::<u8>(array, *p, *s),
(UInt16, UInt8) => primitive_to_primitive_dyn::<u16, u8>(array, to_type, options),
(UInt16, UInt32) => primitive_to_primitive_dyn::<u16, u32>(array, to_type, as_options),
(UInt16, UInt64) => primitive_to_primitive_dyn::<u16, u64>(array, to_type, as_options),
(UInt16, Int8) => primitive_to_primitive_dyn::<u16, i8>(array, to_type, options),
(UInt16, Int16) => primitive_to_primitive_dyn::<u16, i16>(array, to_type, options),
(UInt16, Int32) => primitive_to_primitive_dyn::<u16, i32>(array, to_type, options),
(UInt16, Int64) => primitive_to_primitive_dyn::<u16, i64>(array, to_type, options),
(UInt16, Float32) => primitive_to_primitive_dyn::<u16, f32>(array, to_type, as_options),
(UInt16, Float64) => primitive_to_primitive_dyn::<u16, f64>(array, to_type, as_options),
(UInt16, Decimal(p, s)) => integer_to_decimal_dyn::<u16>(array, *p, *s),
(UInt32, UInt8) => primitive_to_primitive_dyn::<u32, u8>(array, to_type, options),
(UInt32, UInt16) => primitive_to_primitive_dyn::<u32, u16>(array, to_type, options),
(UInt32, UInt64) => primitive_to_primitive_dyn::<u32, u64>(array, to_type, as_options),
(UInt32, Int8) => primitive_to_primitive_dyn::<u32, i8>(array, to_type, options),
(UInt32, Int16) => primitive_to_primitive_dyn::<u32, i16>(array, to_type, options),
(UInt32, Int32) => primitive_to_primitive_dyn::<u32, i32>(array, to_type, options),
(UInt32, Int64) => primitive_to_primitive_dyn::<u32, i64>(array, to_type, options),
(UInt32, Float32) => primitive_to_primitive_dyn::<u32, f32>(array, to_type, as_options),
(UInt32, Float64) => primitive_to_primitive_dyn::<u32, f64>(array, to_type, as_options),
(UInt32, Decimal(p, s)) => integer_to_decimal_dyn::<u32>(array, *p, *s),
(UInt64, UInt8) => primitive_to_primitive_dyn::<u64, u8>(array, to_type, options),
(UInt64, UInt16) => primitive_to_primitive_dyn::<u64, u16>(array, to_type, options),
(UInt64, UInt32) => primitive_to_primitive_dyn::<u64, u32>(array, to_type, options),
(UInt64, Int8) => primitive_to_primitive_dyn::<u64, i8>(array, to_type, options),
(UInt64, Int16) => primitive_to_primitive_dyn::<u64, i16>(array, to_type, options),
(UInt64, Int32) => primitive_to_primitive_dyn::<u64, i32>(array, to_type, options),
(UInt64, Int64) => primitive_to_primitive_dyn::<u64, i64>(array, to_type, options),
(UInt64, Float32) => primitive_to_primitive_dyn::<u64, f32>(array, to_type, as_options),
(UInt64, Float64) => primitive_to_primitive_dyn::<u64, f64>(array, to_type, as_options),
(UInt64, Decimal(p, s)) => integer_to_decimal_dyn::<u64>(array, *p, *s),
(Int8, UInt8) => primitive_to_primitive_dyn::<i8, u8>(array, to_type, options),
(Int8, UInt16) => primitive_to_primitive_dyn::<i8, u16>(array, to_type, options),
(Int8, UInt32) => primitive_to_primitive_dyn::<i8, u32>(array, to_type, options),
(Int8, UInt64) => primitive_to_primitive_dyn::<i8, u64>(array, to_type, options),
(Int8, Int16) => primitive_to_primitive_dyn::<i8, i16>(array, to_type, as_options),
(Int8, Int32) => primitive_to_primitive_dyn::<i8, i32>(array, to_type, as_options),
(Int8, Int64) => primitive_to_primitive_dyn::<i8, i64>(array, to_type, as_options),
(Int8, Float32) => primitive_to_primitive_dyn::<i8, f32>(array, to_type, as_options),
(Int8, Float64) => primitive_to_primitive_dyn::<i8, f64>(array, to_type, as_options),
(Int8, Decimal(p, s)) => integer_to_decimal_dyn::<i8>(array, *p, *s),
(Int16, UInt8) => primitive_to_primitive_dyn::<i16, u8>(array, to_type, options),
(Int16, UInt16) => primitive_to_primitive_dyn::<i16, u16>(array, to_type, options),
(Int16, UInt32) => primitive_to_primitive_dyn::<i16, u32>(array, to_type, options),
(Int16, UInt64) => primitive_to_primitive_dyn::<i16, u64>(array, to_type, options),
(Int16, Int8) => primitive_to_primitive_dyn::<i16, i8>(array, to_type, options),
(Int16, Int32) => primitive_to_primitive_dyn::<i16, i32>(array, to_type, as_options),
(Int16, Int64) => primitive_to_primitive_dyn::<i16, i64>(array, to_type, as_options),
(Int16, Float32) => primitive_to_primitive_dyn::<i16, f32>(array, to_type, as_options),
(Int16, Float64) => primitive_to_primitive_dyn::<i16, f64>(array, to_type, as_options),
(Int16, Decimal(p, s)) => integer_to_decimal_dyn::<i16>(array, *p, *s),
(Int32, UInt8) => primitive_to_primitive_dyn::<i32, u8>(array, to_type, options),
(Int32, UInt16) => primitive_to_primitive_dyn::<i32, u16>(array, to_type, options),
(Int32, UInt32) => primitive_to_primitive_dyn::<i32, u32>(array, to_type, options),
(Int32, UInt64) => primitive_to_primitive_dyn::<i32, u64>(array, to_type, options),
(Int32, Int8) => primitive_to_primitive_dyn::<i32, i8>(array, to_type, options),
(Int32, Int16) => primitive_to_primitive_dyn::<i32, i16>(array, to_type, options),
(Int32, Int64) => primitive_to_primitive_dyn::<i32, i64>(array, to_type, as_options),
(Int32, Float32) => primitive_to_primitive_dyn::<i32, f32>(array, to_type, as_options),
(Int32, Float64) => primitive_to_primitive_dyn::<i32, f64>(array, to_type, as_options),
(Int32, Decimal(p, s)) => integer_to_decimal_dyn::<i32>(array, *p, *s),
(Int64, UInt8) => primitive_to_primitive_dyn::<i64, u8>(array, to_type, options),
(Int64, UInt16) => primitive_to_primitive_dyn::<i64, u16>(array, to_type, options),
(Int64, UInt32) => primitive_to_primitive_dyn::<i64, u32>(array, to_type, options),
(Int64, UInt64) => primitive_to_primitive_dyn::<i64, u64>(array, to_type, options),
(Int64, Int8) => primitive_to_primitive_dyn::<i64, i8>(array, to_type, options),
(Int64, Int16) => primitive_to_primitive_dyn::<i64, i16>(array, to_type, options),
(Int64, Int32) => primitive_to_primitive_dyn::<i64, i32>(array, to_type, options),
(Int64, Float32) => primitive_to_primitive_dyn::<i64, f32>(array, to_type, options),
(Int64, Float64) => primitive_to_primitive_dyn::<i64, f64>(array, to_type, as_options),
(Int64, Decimal(p, s)) => integer_to_decimal_dyn::<i64>(array, *p, *s),
(Float16, Float32) => {
let from = array.as_any().downcast_ref().unwrap();
Ok(f16_to_f32(from).boxed())
}
(Float32, UInt8) => primitive_to_primitive_dyn::<f32, u8>(array, to_type, options),
(Float32, UInt16) => primitive_to_primitive_dyn::<f32, u16>(array, to_type, options),
(Float32, UInt32) => primitive_to_primitive_dyn::<f32, u32>(array, to_type, options),
(Float32, UInt64) => primitive_to_primitive_dyn::<f32, u64>(array, to_type, options),
(Float32, Int8) => primitive_to_primitive_dyn::<f32, i8>(array, to_type, options),
(Float32, Int16) => primitive_to_primitive_dyn::<f32, i16>(array, to_type, options),
(Float32, Int32) => primitive_to_primitive_dyn::<f32, i32>(array, to_type, options),
(Float32, Int64) => primitive_to_primitive_dyn::<f32, i64>(array, to_type, options),
(Float32, Float64) => primitive_to_primitive_dyn::<f32, f64>(array, to_type, as_options),
(Float32, Decimal(p, s)) => float_to_decimal_dyn::<f32>(array, *p, *s),
(Float64, UInt8) => primitive_to_primitive_dyn::<f64, u8>(array, to_type, options),
(Float64, UInt16) => primitive_to_primitive_dyn::<f64, u16>(array, to_type, options),
(Float64, UInt32) => primitive_to_primitive_dyn::<f64, u32>(array, to_type, options),
(Float64, UInt64) => primitive_to_primitive_dyn::<f64, u64>(array, to_type, options),
(Float64, Int8) => primitive_to_primitive_dyn::<f64, i8>(array, to_type, options),
(Float64, Int16) => primitive_to_primitive_dyn::<f64, i16>(array, to_type, options),
(Float64, Int32) => primitive_to_primitive_dyn::<f64, i32>(array, to_type, options),
(Float64, Int64) => primitive_to_primitive_dyn::<f64, i64>(array, to_type, options),
(Float64, Float32) => primitive_to_primitive_dyn::<f64, f32>(array, to_type, options),
(Float64, Decimal(p, s)) => float_to_decimal_dyn::<f64>(array, *p, *s),
(Decimal(_, _), UInt8) => decimal_to_integer_dyn::<u8>(array),
(Decimal(_, _), UInt16) => decimal_to_integer_dyn::<u16>(array),
(Decimal(_, _), UInt32) => decimal_to_integer_dyn::<u32>(array),
(Decimal(_, _), UInt64) => decimal_to_integer_dyn::<u64>(array),
(Decimal(_, _), Int8) => decimal_to_integer_dyn::<i8>(array),
(Decimal(_, _), Int16) => decimal_to_integer_dyn::<i16>(array),
(Decimal(_, _), Int32) => decimal_to_integer_dyn::<i32>(array),
(Decimal(_, _), Int64) => decimal_to_integer_dyn::<i64>(array),
(Decimal(_, _), Float32) => decimal_to_float_dyn::<f32>(array),
(Decimal(_, _), Float64) => decimal_to_float_dyn::<f64>(array),
(Decimal(_, _), Decimal(to_p, to_s)) => decimal_to_decimal_dyn(array, *to_p, *to_s),
// end numeric casts
// temporal casts
(Int32, Date32) => primitive_to_same_primitive_dyn::<i32>(array, to_type),
(Int32, Time32(TimeUnit::Second)) => primitive_to_same_primitive_dyn::<i32>(array, to_type),
(Int32, Time32(TimeUnit::Millisecond)) => {
primitive_to_same_primitive_dyn::<i32>(array, to_type)
}
// No support for microsecond/nanosecond with i32
(Date32, Int32) => primitive_to_same_primitive_dyn::<i32>(array, to_type),
(Date32, Int64) => primitive_to_primitive_dyn::<i32, i64>(array, to_type, options),
(Time32(_), Int32) => primitive_to_same_primitive_dyn::<i32>(array, to_type),
(Int64, Date64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
// No support for second/milliseconds with i64
(Int64, Time64(TimeUnit::Microsecond)) => {
primitive_to_same_primitive_dyn::<i64>(array, to_type)
}
(Int64, Time64(TimeUnit::Nanosecond)) => {
primitive_to_same_primitive_dyn::<i64>(array, to_type)
}
(Date64, Int32) => primitive_to_primitive_dyn::<i64, i32>(array, to_type, options),
(Date64, Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
(Time64(_), Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
(Date32, Date64) => primitive_dyn!(array, date32_to_date64),
(Date64, Date32) => primitive_dyn!(array, date64_to_date32),
(Time32(TimeUnit::Second), Time32(TimeUnit::Millisecond)) => {
primitive_dyn!(array, time32s_to_time32ms)
}
(Time32(TimeUnit::Millisecond), Time32(TimeUnit::Second)) => {
primitive_dyn!(array, time32ms_to_time32s)
}
(Time32(from_unit), Time64(to_unit)) => {
primitive_dyn!(array, time32_to_time64, *from_unit, *to_unit)
}
(Time64(TimeUnit::Microsecond), Time64(TimeUnit::Nanosecond)) => {
primitive_dyn!(array, time64us_to_time64ns)
}
(Time64(TimeUnit::Nanosecond), Time64(TimeUnit::Microsecond)) => {
primitive_dyn!(array, time64ns_to_time64us)
}
(Time64(from_unit), Time32(to_unit)) => {
primitive_dyn!(array, time64_to_time32, *from_unit, *to_unit)
}
(Timestamp(_, _), Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
(Int64, Timestamp(_, _)) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
(Timestamp(from_unit, _), Timestamp(to_unit, tz)) => {
primitive_dyn!(array, timestamp_to_timestamp, *from_unit, *to_unit, tz)
}
(Timestamp(from_unit, _), Date32) => primitive_dyn!(array, timestamp_to_date32, *from_unit),
(Timestamp(from_unit, _), Date64) => primitive_dyn!(array, timestamp_to_date64, *from_unit),
(Int64, Duration(_)) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
(Duration(_), Int64) => primitive_to_same_primitive_dyn::<i64>(array, to_type),
(Interval(IntervalUnit::DayTime), Interval(IntervalUnit::MonthDayNano)) => {
primitive_dyn!(array, days_ms_to_months_days_ns)
}
(Interval(IntervalUnit::YearMonth), Interval(IntervalUnit::MonthDayNano)) => {
primitive_dyn!(array, months_to_months_days_ns)
}
(_, _) => Err(Error::NotYetImplemented(format!(
"Casting from {:?} to {:?} not supported",
from_type, to_type,
))),
}
}
sourcepub fn arced(self) -> Arc<dyn Array>
pub fn arced(self) -> Arc<dyn Array>
Boxes self into a std::sync::Arc<dyn Array>
.
sourcepub fn new(
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>
) -> Self
pub fn new(
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>
) -> Self
Alias for Self::try_new(..).unwrap()
.
Panics
This function errors iff:
- The validity is not
None
and its length is different fromvalues
’s length - The
data_type
’sPhysicalType
is not equal toPhysicalType::Primitive
.
Examples found in repository?
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
pub fn from_vec(values: Vec<T>) -> Self {
Self::new(T::PRIMITIVE.into(), values.into(), None)
}
/// Returns an iterator over the values and validity, `Option<&T>`.
#[inline]
pub fn iter(&self) -> ZipValidity<&T, std::slice::Iter<T>, BitmapIter> {
ZipValidity::new_with_validity(self.values().iter(), self.validity())
}
/// Returns an iterator of the values, `&T`, ignoring the arrays' validity.
#[inline]
pub fn values_iter(&self) -> std::slice::Iter<T> {
self.values().iter()
}
/// Returns the length of this array
#[inline]
pub fn len(&self) -> usize {
self.values.len()
}
/// The values [`Buffer`].
/// Values on null slots are undetermined (they can be anything).
#[inline]
pub fn values(&self) -> &Buffer<T> {
&self.values
}
/// Returns the optional validity.
#[inline]
pub fn validity(&self) -> Option<&Bitmap> {
self.validity.as_ref()
}
/// Returns the arrays' [`DataType`].
#[inline]
pub fn data_type(&self) -> &DataType {
&self.data_type
}
/// Returns the value at slot `i`.
///
/// Equivalent to `self.values()[i]`. The value of a null slot is undetermined (it can be anything).
/// # Panic
/// This function panics iff `i >= self.len`.
#[inline]
pub fn value(&self, i: usize) -> T {
self.values()[i]
}
/// Returns the value at index `i`.
/// The value on null slots is undetermined (it can be anything).
/// # Safety
/// Caller must be sure that `i < self.len()`
#[inline]
pub unsafe fn value_unchecked(&self, i: usize) -> T {
*self.values.get_unchecked(i)
}
/// Returns a clone of this [`PrimitiveArray`] sliced by an offset and length.
/// # Implementation
/// This operation is `O(1)` as it amounts to increase two ref counts.
/// # Examples
/// ```
/// use arrow2::array::PrimitiveArray;
///
/// let array = PrimitiveArray::from_vec(vec![1, 2, 3]);
/// assert_eq!(format!("{:?}", array), "Int32[1, 2, 3]");
/// let sliced = array.slice(1, 1);
/// assert_eq!(format!("{:?}", sliced), "Int32[2]");
/// // note: `sliced` and `array` share the same memory region.
/// ```
/// # Panic
/// This function panics iff `offset + length > self.len()`.
#[inline]
#[must_use]
pub fn slice(&self, offset: usize, length: usize) -> Self {
assert!(
offset + length <= self.len(),
"offset + length may not exceed length of array"
);
unsafe { self.slice_unchecked(offset, length) }
}
/// Returns a clone of this [`PrimitiveArray`] sliced by an offset and length.
/// # Implementation
/// This operation is `O(1)` as it amounts to increase two ref counts.
/// # Safety
/// The caller must ensure that `offset + length <= self.len()`.
#[inline]
#[must_use]
pub unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Self {
let validity = self
.validity
.clone()
.map(|bitmap| bitmap.slice_unchecked(offset, length))
.and_then(|bitmap| (bitmap.unset_bits() > 0).then(|| bitmap));
Self {
data_type: self.data_type.clone(),
values: self.values.clone().slice_unchecked(offset, length),
validity,
}
}
/// Returns this [`PrimitiveArray`] with a new validity.
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
#[must_use]
pub fn with_validity(mut self, validity: Option<Bitmap>) -> Self {
self.set_validity(validity);
self
}
/// Sets the validity of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `validity.len() != self.len()`.
pub fn set_validity(&mut self, validity: Option<Bitmap>) {
if matches!(&validity, Some(bitmap) if bitmap.len() != self.len()) {
panic!("validity's length must be equal to the array's length")
}
self.validity = validity;
}
/// Returns this [`PrimitiveArray`] with new values.
/// # Panics
/// This function panics iff `values.len() != self.len()`.
#[must_use]
pub fn with_values(mut self, values: Buffer<T>) -> Self {
self.set_values(values);
self
}
/// Update the values of this [`PrimitiveArray`].
/// # Panics
/// This function panics iff `values.len() != self.len()`.
pub fn set_values(&mut self, values: Buffer<T>) {
assert_eq!(
values.len(),
self.len(),
"values' length must be equal to this arrays' length"
);
self.values = values;
}
/// Applies a function `f` to the validity of this array.
///
/// This is an API to leverage clone-on-write
/// # Panics
/// This function panics if the function `f` modifies the length of the [`Bitmap`].
pub fn apply_validity<F: FnOnce(Bitmap) -> Bitmap>(&mut self, f: F) {
if let Some(validity) = std::mem::take(&mut self.validity) {
self.set_validity(Some(f(validity)))
}
}
/// Returns an option of a mutable reference to the values of this [`PrimitiveArray`].
pub fn get_mut_values(&mut self) -> Option<&mut [T]> {
self.values.get_mut().map(|x| x.as_mut())
}
/// Returns its internal representation
#[must_use]
pub fn into_inner(self) -> (DataType, Buffer<T>, Option<Bitmap>) {
let Self {
data_type,
values,
validity,
} = self;
(data_type, values, validity)
}
/// Try to convert this [`PrimitiveArray`] to a [`MutablePrimitiveArray`] via copy-on-write semantics.
///
/// A [`PrimitiveArray`] is backed by a [`Buffer`] and [`Bitmap`] which are essentially `Arc<Vec<_>>`.
/// This function returns a [`MutablePrimitiveArray`] (via [`std::sync::Arc::get_mut`]) iff both values
/// and validity have not been cloned / are unique references to their underlying vectors.
///
/// This function is primarily used to re-use memory regions.
#[must_use]
pub fn into_mut(mut self) -> Either<Self, MutablePrimitiveArray<T>> {
use Either::*;
if let Some(bitmap) = self.validity {
match bitmap.into_mut() {
Left(bitmap) => Left(PrimitiveArray::new(
self.data_type,
self.values,
Some(bitmap),
)),
Right(mutable_bitmap) => match self.values.get_mut().map(std::mem::take) {
Some(values) => Right(
MutablePrimitiveArray::try_new(
self.data_type,
values,
Some(mutable_bitmap),
)
.unwrap(),
),
None => Left(PrimitiveArray::new(
self.data_type,
self.values,
Some(mutable_bitmap.into()),
)),
},
}
} else {
match self.values.get_mut().map(std::mem::take) {
Some(values) => {
Right(MutablePrimitiveArray::try_new(self.data_type, values, None).unwrap())
}
None => Left(PrimitiveArray::new(self.data_type, self.values, None)),
}
}
}
/// Returns a new empty (zero-length) [`PrimitiveArray`].
pub fn new_empty(data_type: DataType) -> Self {
Self::new(data_type, Buffer::new(), None)
}
/// Returns a new [`PrimitiveArray`] where all slots are null / `None`.
#[inline]
pub fn new_null(data_type: DataType, length: usize) -> Self {
Self::new(
data_type,
vec![T::default(); length].into(),
Some(Bitmap::new_zeroed(length)),
)
}
/// Creates a (non-null) [`PrimitiveArray`] from an iterator of values.
/// # Implementation
/// This does not assume that the iterator has a known length.
pub fn from_values<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self::new(T::PRIMITIVE.into(), Vec::<T>::from_iter(iter).into(), None)
}
/// Creates a (non-null) [`PrimitiveArray`] from a slice of values.
/// # Implementation
/// This is essentially a memcopy and is thus `O(N)`
pub fn from_slice<P: AsRef<[T]>>(slice: P) -> Self {
Self::new(
T::PRIMITIVE.into(),
Vec::<T>::from(slice.as_ref()).into(),
None,
)
}
/// Creates a (non-null) [`PrimitiveArray`] from a [`TrustedLen`] of values.
/// # Implementation
/// This does not assume that the iterator has a known length.
pub fn from_trusted_len_values_iter<I: TrustedLen<Item = T>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_values_iter(iter).into()
}
/// Creates a new [`PrimitiveArray`] from an iterator over values
/// # Safety
/// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
/// I.e. that `size_hint().1` correctly reports its length.
pub unsafe fn from_trusted_len_values_iter_unchecked<I: Iterator<Item = T>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_values_iter_unchecked(iter).into()
}
/// Creates a [`PrimitiveArray`] from a [`TrustedLen`] of optional values.
pub fn from_trusted_len_iter<I: TrustedLen<Item = Option<T>>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_iter(iter).into()
}
/// Creates a [`PrimitiveArray`] from an iterator of optional values.
/// # Safety
/// The iterator must be [`TrustedLen`](https://doc.rust-lang.org/std/iter/trait.TrustedLen.html).
/// I.e. that `size_hint().1` correctly reports its length.
pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = Option<T>>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_iter_unchecked(iter).into()
}
/// Boxes self into a [`Box<dyn Array>`].
pub fn boxed(self) -> Box<dyn Array> {
Box::new(self)
}
/// Boxes self into a [`std::sync::Arc<dyn Array>`].
pub fn arced(self) -> std::sync::Arc<dyn Array> {
std::sync::Arc::new(self)
}
/// Alias for `Self::try_new(..).unwrap()`.
/// # Panics
/// This function errors iff:
/// * The validity is not `None` and its length is different from `values`'s length
/// * The `data_type`'s [`PhysicalType`] is not equal to [`PhysicalType::Primitive`].
pub fn new(data_type: DataType, values: Buffer<T>, validity: Option<Bitmap>) -> Self {
Self::try_new(data_type, values, validity).unwrap()
}
}
impl<T: NativeType> Array for PrimitiveArray<T> {
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn len(&self) -> usize {
self.values.len()
}
#[inline]
fn data_type(&self) -> &DataType {
self.data_type()
}
fn validity(&self) -> Option<&Bitmap> {
self.validity.as_ref()
}
fn slice(&self, offset: usize, length: usize) -> Box<dyn Array> {
Box::new(self.slice(offset, length))
}
unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Box<dyn Array> {
Box::new(self.slice_unchecked(offset, length))
}
fn with_validity(&self, validity: Option<Bitmap>) -> Box<dyn Array> {
Box::new(self.clone().with_validity(validity))
}
fn to_boxed(&self) -> Box<dyn Array> {
Box::new(self.clone())
}
}
/// A type definition [`PrimitiveArray`] for `i8`
pub type Int8Array = PrimitiveArray<i8>;
/// A type definition [`PrimitiveArray`] for `i16`
pub type Int16Array = PrimitiveArray<i16>;
/// A type definition [`PrimitiveArray`] for `i32`
pub type Int32Array = PrimitiveArray<i32>;
/// A type definition [`PrimitiveArray`] for `i64`
pub type Int64Array = PrimitiveArray<i64>;
/// A type definition [`PrimitiveArray`] for `i128`
pub type Int128Array = PrimitiveArray<i128>;
/// A type definition [`PrimitiveArray`] for `i256`
pub type Int256Array = PrimitiveArray<i256>;
/// A type definition [`PrimitiveArray`] for [`days_ms`]
pub type DaysMsArray = PrimitiveArray<days_ms>;
/// A type definition [`PrimitiveArray`] for [`months_days_ns`]
pub type MonthsDaysNsArray = PrimitiveArray<months_days_ns>;
/// A type definition [`PrimitiveArray`] for `f16`
pub type Float16Array = PrimitiveArray<f16>;
/// A type definition [`PrimitiveArray`] for `f32`
pub type Float32Array = PrimitiveArray<f32>;
/// A type definition [`PrimitiveArray`] for `f64`
pub type Float64Array = PrimitiveArray<f64>;
/// A type definition [`PrimitiveArray`] for `u8`
pub type UInt8Array = PrimitiveArray<u8>;
/// A type definition [`PrimitiveArray`] for `u16`
pub type UInt16Array = PrimitiveArray<u16>;
/// A type definition [`PrimitiveArray`] for `u32`
pub type UInt32Array = PrimitiveArray<u32>;
/// A type definition [`PrimitiveArray`] for `u64`
pub type UInt64Array = PrimitiveArray<u64>;
/// A type definition [`MutablePrimitiveArray`] for `i8`
pub type Int8Vec = MutablePrimitiveArray<i8>;
/// A type definition [`MutablePrimitiveArray`] for `i16`
pub type Int16Vec = MutablePrimitiveArray<i16>;
/// A type definition [`MutablePrimitiveArray`] for `i32`
pub type Int32Vec = MutablePrimitiveArray<i32>;
/// A type definition [`MutablePrimitiveArray`] for `i64`
pub type Int64Vec = MutablePrimitiveArray<i64>;
/// A type definition [`MutablePrimitiveArray`] for `i128`
pub type Int128Vec = MutablePrimitiveArray<i128>;
/// A type definition [`MutablePrimitiveArray`] for `i256`
pub type Int256Vec = MutablePrimitiveArray<i256>;
/// A type definition [`MutablePrimitiveArray`] for [`days_ms`]
pub type DaysMsVec = MutablePrimitiveArray<days_ms>;
/// A type definition [`MutablePrimitiveArray`] for [`months_days_ns`]
pub type MonthsDaysNsVec = MutablePrimitiveArray<months_days_ns>;
/// A type definition [`MutablePrimitiveArray`] for `f16`
pub type Float16Vec = MutablePrimitiveArray<f16>;
/// A type definition [`MutablePrimitiveArray`] for `f32`
pub type Float32Vec = MutablePrimitiveArray<f32>;
/// A type definition [`MutablePrimitiveArray`] for `f64`
pub type Float64Vec = MutablePrimitiveArray<f64>;
/// A type definition [`MutablePrimitiveArray`] for `u8`
pub type UInt8Vec = MutablePrimitiveArray<u8>;
/// A type definition [`MutablePrimitiveArray`] for `u16`
pub type UInt16Vec = MutablePrimitiveArray<u16>;
/// A type definition [`MutablePrimitiveArray`] for `u32`
pub type UInt32Vec = MutablePrimitiveArray<u32>;
/// A type definition [`MutablePrimitiveArray`] for `u64`
pub type UInt64Vec = MutablePrimitiveArray<u64>;
impl<T: NativeType> Default for PrimitiveArray<T> {
fn default() -> Self {
PrimitiveArray::new(T::PRIMITIVE.into(), Default::default(), None)
}
More examples
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
fn primitive<T: NativeType>(data_type: DataType, values: &[T]) -> PrimitiveArray<T> {
PrimitiveArray::new(data_type, values.to_vec().into(), None)
}
fn primitive_optional<T: NativeType>(
data_type: DataType,
values: &[T],
indicators: &[isize],
) -> PrimitiveArray<T> {
let validity = bitmap(indicators);
PrimitiveArray::new(data_type, values.to_vec().into(), validity)
}
fn bool(data_type: DataType, values: &[Bit]) -> BooleanArray {
let values = values.iter().map(|x| x.as_bool());
let values = Bitmap::from_trusted_len_iter(values);
BooleanArray::new(data_type, values, None)
}
fn bool_optional(data_type: DataType, values: &[Bit], indicators: &[isize]) -> BooleanArray {
let validity = bitmap(indicators);
let values = values.iter().map(|x| x.as_bool());
let values = Bitmap::from_trusted_len_iter(values);
BooleanArray::new(data_type, values, validity)
}
fn binary_generic<'a>(
iter: impl Iterator<Item = Option<&'a [u8]>>,
) -> (OffsetsBuffer<i32>, Buffer<u8>, Option<Bitmap>) {
let length = iter.size_hint().0;
let mut validity = MutableBitmap::with_capacity(length);
let mut values = Vec::<u8>::with_capacity(0);
let mut offsets = Offsets::<i32>::with_capacity(length);
for item in iter {
if let Some(item) = item {
values.extend_from_slice(item);
offsets
.try_push_usize(item.len())
.expect("List to contain less than i32::MAX items.");
validity.push(true);
} else {
offsets.extend_constant(1);
validity.push(false);
}
}
(offsets.into(), values.into(), validity.into())
}
fn binary(data_type: DataType, view: BinColumnView) -> BinaryArray<i32> {
let (offsets, values, validity) = binary_generic(view.iter());
BinaryArray::new(data_type, offsets, values, validity)
}
fn utf8(data_type: DataType, view: TextColumnView<u8>) -> Utf8Array<i32> {
let (offsets, values, validity) = binary_generic(view.iter());
// this O(N) check is necessary for the utf8 validity
Utf8Array::new(data_type, offsets, values, validity)
}
fn date(data_type: DataType, values: &[odbc_api::sys::Date]) -> PrimitiveArray<i32> {
let values = values.iter().map(days_since_epoch).collect::<Vec<_>>();
PrimitiveArray::new(data_type, values.into(), None)
}
fn date_optional(
data_type: DataType,
values: &[odbc_api::sys::Date],
indicators: &[isize],
) -> PrimitiveArray<i32> {
let values = values.iter().map(days_since_epoch).collect::<Vec<_>>();
let validity = bitmap(indicators);
PrimitiveArray::new(data_type, values.into(), validity)
}
fn days_since_epoch(date: &odbc_api::sys::Date) -> i32 {
let unix_epoch = NaiveDate::from_ymd_opt(1970, 1, 1).expect("invalid or out-of-range date");
let date = NaiveDate::from_ymd_opt(date.year as i32, date.month as u32, date.day as u32)
.unwrap_or(unix_epoch);
let duration = date.signed_duration_since(unix_epoch);
duration.num_days().try_into().unwrap_or(i32::MAX)
}
fn time(data_type: DataType, values: &[odbc_api::sys::Time]) -> PrimitiveArray<i32> {
let values = values.iter().map(time_since_midnight).collect::<Vec<_>>();
PrimitiveArray::new(data_type, values.into(), None)
}
fn time_since_midnight(date: &odbc_api::sys::Time) -> i32 {
(date.hour as i32) * 60 * 60 + (date.minute as i32) * 60 + date.second as i32
}
fn time_optional(
data_type: DataType,
values: &[odbc_api::sys::Time],
indicators: &[isize],
) -> PrimitiveArray<i32> {
let values = values.iter().map(time_since_midnight).collect::<Vec<_>>();
let validity = bitmap(indicators);
PrimitiveArray::new(data_type, values.into(), validity)
}
fn timestamp(data_type: DataType, values: &[odbc_api::sys::Timestamp]) -> PrimitiveArray<i64> {
let unit = if let DataType::Timestamp(unit, _) = &data_type {
unit
} else {
unreachable!()
};
let values = match unit {
TimeUnit::Second => values.iter().map(timestamp_s).collect::<Vec<_>>(),
TimeUnit::Millisecond => values.iter().map(timestamp_ms).collect::<Vec<_>>(),
TimeUnit::Microsecond => values.iter().map(timestamp_us).collect::<Vec<_>>(),
TimeUnit::Nanosecond => values.iter().map(timestamp_ns).collect::<Vec<_>>(),
};
PrimitiveArray::new(data_type, values.into(), None)
}
fn timestamp_optional(
data_type: DataType,
values: &[odbc_api::sys::Timestamp],
indicators: &[isize],
) -> PrimitiveArray<i64> {
let unit = if let DataType::Timestamp(unit, _) = &data_type {
unit
} else {
unreachable!()
};
let values = match unit {
TimeUnit::Second => values.iter().map(timestamp_s).collect::<Vec<_>>(),
TimeUnit::Millisecond => values.iter().map(timestamp_ms).collect::<Vec<_>>(),
TimeUnit::Microsecond => values.iter().map(timestamp_us).collect::<Vec<_>>(),
TimeUnit::Nanosecond => values.iter().map(timestamp_ns).collect::<Vec<_>>(),
};
let validity = bitmap(indicators);
PrimitiveArray::new(data_type, values.into(), validity)
}
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
fn to(&mut self) -> PrimitiveArray<T> {
let validity = std::mem::take(&mut self.validity);
let values = std::mem::take(&mut self.values);
PrimitiveArray::<T>::new(self.data_type.clone(), values.into(), validity.into())
}
}
impl<'a, T: NativeType> Growable<'a> for GrowablePrimitive<'a, T> {
#[inline]
fn extend(&mut self, index: usize, start: usize, len: usize) {
(self.extend_null_bits[index])(&mut self.validity, start, len);
let values = self.arrays[index];
self.values.extend_from_slice(&values[start..start + len]);
}
#[inline]
fn extend_validity(&mut self, additional: usize) {
self.values
.resize(self.values.len() + additional, T::default());
self.validity.extend_constant(additional, false);
}
#[inline]
fn as_arc(&mut self) -> Arc<dyn Array> {
Arc::new(self.to())
}
#[inline]
fn as_box(&mut self) -> Box<dyn Array> {
Box::new(self.to())
}
}
impl<'a, T: NativeType> From<GrowablePrimitive<'a, T>> for PrimitiveArray<T> {
#[inline]
fn from(val: GrowablePrimitive<'a, T>) -> Self {
PrimitiveArray::<T>::new(val.data_type, val.values.into(), val.validity.into())
}
267 268 269 270 271 272 273 274 275 276 277 278 279
pub fn primitive_to_same_primitive<T>(
from: &PrimitiveArray<T>,
to_type: &DataType,
) -> PrimitiveArray<T>
where
T: NativeType,
{
PrimitiveArray::<T>::new(
to_type.clone(),
from.values().clone(),
from.validity().cloned(),
)
}
- src/compute/hash.rs
- src/compute/arity.rs
- src/compute/cast/boolean_to.rs
- src/io/json_integration/read/array.rs
- src/array/primitive/mutable.rs
- src/io/parquet/read/deserialize/primitive/dictionary.rs
- src/compute/nullif.rs
- src/compute/length.rs
- src/compute/filter.rs
- src/compute/cast/decimal_to.rs
- src/compute/take/primitive.rs
- src/array/growable/dictionary.rs
- src/compute/sort/primitive/sort.rs
- src/compute/sort/boolean.rs
- src/compute/sort/mod.rs
- src/compute/arithmetics/decimal/add.rs
- src/compute/arithmetics/decimal/sub.rs
- src/compute/arithmetics/decimal/mul.rs
- src/compute/arithmetics/decimal/div.rs
- src/compute/sort/lex_sort.rs
- src/compute/sort/common.rs
- src/io/parquet/write/mod.rs
Trait Implementations§
source§impl<T: NativeType> Array for PrimitiveArray<T>
impl<T: NativeType> Array for PrimitiveArray<T>
source§fn as_any(&self) -> &dyn Any
fn as_any(&self) -> &dyn Any
Any
, which enables downcasting to concrete types.source§fn as_any_mut(&mut self) -> &mut dyn Any
fn as_any_mut(&mut self) -> &mut dyn Any
Any
, which enables mutable downcasting to concrete types.source§fn len(&self) -> usize
fn len(&self) -> usize
Array
. Every array has a length corresponding to the number of
elements (slots).source§fn data_type(&self) -> &DataType
fn data_type(&self) -> &DataType
DataType
of the Array
. In combination with Array::as_any
, this can be
used to downcast trait objects (dyn Array
) to concrete arrays.source§impl<T> ArrayAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Add<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Add<Output = T>,
compute_arithmetics
only.source§fn add(&self, rhs: &PrimitiveArray<T>) -> Self
fn add(&self, rhs: &PrimitiveArray<T>) -> Self
rhs
source§impl ArrayAdd<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArrayAdd<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn add(&self, rhs: &PrimitiveArray<i128>) -> Self
fn add(&self, rhs: &PrimitiveArray<i128>) -> Self
rhs
source§impl<T> ArrayAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + Add<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + Add<Output = T>,
compute_arithmetics
only.source§impl<T> ArrayCheckedAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedAdd<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedAdd<Output = T>,
compute_arithmetics
only.source§fn checked_add(&self, rhs: &PrimitiveArray<T>) -> Self
fn checked_add(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArrayCheckedAdd<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArrayCheckedAdd<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn checked_add(&self, rhs: &PrimitiveArray<i128>) -> Self
fn checked_add(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArrayCheckedAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedAdd<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedAdd<Output = T>,
compute_arithmetics
only.source§fn checked_add(&self, rhs: &T) -> Self
fn checked_add(&self, rhs: &T) -> Self
source§impl<T> ArrayCheckedDiv<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedDiv<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedDiv<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedDiv<Output = T>,
compute_arithmetics
only.source§fn checked_div(&self, rhs: &PrimitiveArray<T>) -> Self
fn checked_div(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArrayCheckedDiv<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArrayCheckedDiv<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn checked_div(&self, rhs: &PrimitiveArray<i128>) -> Self
fn checked_div(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArrayCheckedDiv<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedDiv<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedDiv<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedDiv<Output = T>,
compute_arithmetics
only.source§fn checked_div(&self, rhs: &T) -> Self
fn checked_div(&self, rhs: &T) -> Self
source§impl<T> ArrayCheckedMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedMul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedMul<Output = T>,
compute_arithmetics
only.source§fn checked_mul(&self, rhs: &PrimitiveArray<T>) -> Self
fn checked_mul(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArrayCheckedMul<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArrayCheckedMul<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn checked_mul(&self, rhs: &PrimitiveArray<i128>) -> Self
fn checked_mul(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArrayCheckedMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedMul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedMul<Output = T>,
compute_arithmetics
only.source§fn checked_mul(&self, rhs: &T) -> Self
fn checked_mul(&self, rhs: &T) -> Self
source§impl<T> ArrayCheckedRem<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedRem<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedRem<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedRem<Output = T>,
compute_arithmetics
only.source§fn checked_rem(&self, rhs: &PrimitiveArray<T>) -> Self
fn checked_rem(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl<T> ArrayCheckedRem<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedRem<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedRem<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedRem<Output = T>,
compute_arithmetics
only.source§fn checked_rem(&self, rhs: &T) -> Self
fn checked_rem(&self, rhs: &T) -> Self
source§impl<T> ArrayCheckedSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedSub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedSub<Output = T>,
compute_arithmetics
only.source§fn checked_sub(&self, rhs: &PrimitiveArray<T>) -> Self
fn checked_sub(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArrayCheckedSub<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArrayCheckedSub<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn checked_sub(&self, rhs: &PrimitiveArray<i128>) -> Self
fn checked_sub(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArrayCheckedSub<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedSub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayCheckedSub<T> for PrimitiveArray<T>where
T: NativeArithmetics + CheckedSub<Output = T>,
compute_arithmetics
only.source§fn checked_sub(&self, rhs: &T) -> Self
fn checked_sub(&self, rhs: &T) -> Self
source§impl<T> ArrayDiv<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Div<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayDiv<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Div<Output = T>,
compute_arithmetics
only.source§fn div(&self, rhs: &PrimitiveArray<T>) -> Self
fn div(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArrayDiv<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArrayDiv<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn div(&self, rhs: &PrimitiveArray<i128>) -> Self
fn div(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArrayDiv<T> for PrimitiveArray<T>where
T: NativeArithmetics + Div<Output = T> + NumCast,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayDiv<T> for PrimitiveArray<T>where
T: NativeArithmetics + Div<Output = T> + NumCast,
compute_arithmetics
only.source§impl<T> ArrayMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Mul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Mul<Output = T>,
compute_arithmetics
only.source§fn mul(&self, rhs: &PrimitiveArray<T>) -> Self
fn mul(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArrayMul<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArrayMul<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn mul(&self, rhs: &PrimitiveArray<i128>) -> Self
fn mul(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArrayMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + Mul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + Mul<Output = T>,
compute_arithmetics
only.source§impl<T> ArrayOverflowingAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingAdd<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayOverflowingAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingAdd<Output = T>,
compute_arithmetics
only.source§fn overflowing_add(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap)
fn overflowing_add(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap)
source§impl<T> ArrayOverflowingAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingAdd<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayOverflowingAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingAdd<Output = T>,
compute_arithmetics
only.source§fn overflowing_add(&self, rhs: &T) -> (Self, Bitmap)
fn overflowing_add(&self, rhs: &T) -> (Self, Bitmap)
source§impl<T> ArrayOverflowingMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingMul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayOverflowingMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingMul<Output = T>,
compute_arithmetics
only.source§fn overflowing_mul(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap)
fn overflowing_mul(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap)
source§impl<T> ArrayOverflowingMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingMul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayOverflowingMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingMul<Output = T>,
compute_arithmetics
only.source§fn overflowing_mul(&self, rhs: &T) -> (Self, Bitmap)
fn overflowing_mul(&self, rhs: &T) -> (Self, Bitmap)
source§impl<T> ArrayOverflowingSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingSub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayOverflowingSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingSub<Output = T>,
compute_arithmetics
only.source§fn overflowing_sub(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap)
fn overflowing_sub(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap)
source§impl<T> ArrayOverflowingSub<T> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingSub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayOverflowingSub<T> for PrimitiveArray<T>where
T: NativeArithmetics + OverflowingSub<Output = T>,
compute_arithmetics
only.source§fn overflowing_sub(&self, rhs: &T) -> (Self, Bitmap)
fn overflowing_sub(&self, rhs: &T) -> (Self, Bitmap)
source§impl<T> ArrayRem<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Rem<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayRem<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Rem<Output = T>,
compute_arithmetics
only.source§fn rem(&self, rhs: &PrimitiveArray<T>) -> Self
fn rem(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl<T> ArrayRem<T> for PrimitiveArray<T>where
T: NativeArithmetics + Rem<Output = T> + NumCast,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayRem<T> for PrimitiveArray<T>where
T: NativeArithmetics + Rem<Output = T> + NumCast,
compute_arithmetics
only.source§impl<T> ArraySaturatingAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingAdd<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySaturatingAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingAdd<Output = T>,
compute_arithmetics
only.source§fn saturating_add(&self, rhs: &PrimitiveArray<T>) -> Self
fn saturating_add(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArraySaturatingAdd<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArraySaturatingAdd<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn saturating_add(&self, rhs: &PrimitiveArray<i128>) -> Self
fn saturating_add(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArraySaturatingAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingAdd<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySaturatingAdd<T> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingAdd<Output = T>,
compute_arithmetics
only.source§fn saturating_add(&self, rhs: &T) -> Self
fn saturating_add(&self, rhs: &T) -> Self
source§impl<T> ArraySaturatingMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingMul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySaturatingMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingMul<Output = T>,
compute_arithmetics
only.source§fn saturating_mul(&self, rhs: &PrimitiveArray<T>) -> Self
fn saturating_mul(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArraySaturatingMul<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArraySaturatingMul<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn saturating_mul(&self, rhs: &PrimitiveArray<i128>) -> Self
fn saturating_mul(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArraySaturatingMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingMul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySaturatingMul<T> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingMul<Output = T>,
compute_arithmetics
only.source§fn saturating_mul(&self, rhs: &T) -> Self
fn saturating_mul(&self, rhs: &T) -> Self
source§impl<T> ArraySaturatingSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingSub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySaturatingSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingSub<Output = T>,
compute_arithmetics
only.source§fn saturating_sub(&self, rhs: &PrimitiveArray<T>) -> Self
fn saturating_sub(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArraySaturatingSub<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArraySaturatingSub<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn saturating_sub(&self, rhs: &PrimitiveArray<i128>) -> Self
fn saturating_sub(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArraySaturatingSub<T> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingSub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySaturatingSub<T> for PrimitiveArray<T>where
T: NativeArithmetics + SaturatingSub<Output = T>,
compute_arithmetics
only.source§fn saturating_sub(&self, rhs: &T) -> Self
fn saturating_sub(&self, rhs: &T) -> Self
source§impl<T> ArraySub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Sub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + Sub<Output = T>,
compute_arithmetics
only.source§fn sub(&self, rhs: &PrimitiveArray<T>) -> Self
fn sub(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl ArraySub<PrimitiveArray<i128>> for PrimitiveArray<i128>
Available on crate feature compute_arithmetics
only.
impl ArraySub<PrimitiveArray<i128>> for PrimitiveArray<i128>
compute_arithmetics
only.source§fn sub(&self, rhs: &PrimitiveArray<i128>) -> Self
fn sub(&self, rhs: &PrimitiveArray<i128>) -> Self
source§impl<T> ArraySub<T> for PrimitiveArray<T>where
T: NativeArithmetics + Sub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArraySub<T> for PrimitiveArray<T>where
T: NativeArithmetics + Sub<Output = T>,
compute_arithmetics
only.source§impl<T> ArrayWrappingAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + WrappingAdd<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayWrappingAdd<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + WrappingAdd<Output = T>,
compute_arithmetics
only.source§fn wrapping_add(&self, rhs: &PrimitiveArray<T>) -> Self
fn wrapping_add(&self, rhs: &PrimitiveArray<T>) -> Self
rhs
using wrapping additionsource§impl<T> ArrayWrappingMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + WrappingMul<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayWrappingMul<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + WrappingMul<Output = T>,
compute_arithmetics
only.source§fn wrapping_mul(&self, rhs: &PrimitiveArray<T>) -> Self
fn wrapping_mul(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl<T> ArrayWrappingSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + WrappingSub<Output = T>,
Available on crate feature compute_arithmetics
only.
impl<T> ArrayWrappingSub<PrimitiveArray<T>> for PrimitiveArray<T>where
T: NativeArithmetics + WrappingSub<Output = T>,
compute_arithmetics
only.source§fn wrapping_sub(&self, rhs: &PrimitiveArray<T>) -> Self
fn wrapping_sub(&self, rhs: &PrimitiveArray<T>) -> Self
source§impl<T: Clone + NativeType> Clone for PrimitiveArray<T>
impl<T: Clone + NativeType> Clone for PrimitiveArray<T>
source§fn clone(&self) -> PrimitiveArray<T>
fn clone(&self) -> PrimitiveArray<T>
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moresource§impl<T: NativeType> Debug for PrimitiveArray<T>
impl<T: NativeType> Debug for PrimitiveArray<T>
source§impl<T: NativeType> Default for PrimitiveArray<T>
impl<T: NativeType> Default for PrimitiveArray<T>
source§impl<'a, T: NativeType> From<GrowablePrimitive<'a, T>> for PrimitiveArray<T>
impl<'a, T: NativeType> From<GrowablePrimitive<'a, T>> for PrimitiveArray<T>
source§fn from(val: GrowablePrimitive<'a, T>) -> Self
fn from(val: GrowablePrimitive<'a, T>) -> Self
source§impl<T: NativeType> From<MutablePrimitiveArray<T>> for PrimitiveArray<T>
impl<T: NativeType> From<MutablePrimitiveArray<T>> for PrimitiveArray<T>
source§fn from(other: MutablePrimitiveArray<T>) -> Self
fn from(other: MutablePrimitiveArray<T>) -> Self
source§impl<T: NativeType, P: AsRef<[Option<T>]>> From<P> for PrimitiveArray<T>
impl<T: NativeType, P: AsRef<[Option<T>]>> From<P> for PrimitiveArray<T>
source§impl<T: NativeType, Ptr: Borrow<Option<T>>> FromIterator<Ptr> for PrimitiveArray<T>
impl<T: NativeType, Ptr: Borrow<Option<T>>> FromIterator<Ptr> for PrimitiveArray<T>
source§fn from_iter<I: IntoIterator<Item = Ptr>>(iter: I) -> Self
fn from_iter<I: IntoIterator<Item = Ptr>>(iter: I) -> Self
source§impl<'a, T: NativeType> IntoIterator for &'a PrimitiveArray<T>
impl<'a, T: NativeType> IntoIterator for &'a PrimitiveArray<T>
source§impl<T: NativeType> IntoIterator for PrimitiveArray<T>
impl<T: NativeType> IntoIterator for PrimitiveArray<T>
source§impl<T: NativeType> PartialEq<&(dyn Array + 'static)> for PrimitiveArray<T>
impl<T: NativeType> PartialEq<&(dyn Array + 'static)> for PrimitiveArray<T>
source§impl<T: NativeType> PartialEq<PrimitiveArray<T>> for &dyn Array
impl<T: NativeType> PartialEq<PrimitiveArray<T>> for &dyn Array
source§fn eq(&self, other: &PrimitiveArray<T>) -> bool
fn eq(&self, other: &PrimitiveArray<T>) -> bool
self
and other
values to be equal, and is used
by ==
.