use crate::bitmap::utils::BitmapIter;
use crate::bitmap::Bitmap;
use crate::trusted_len::TrustedLen;
#[derive(Debug, Clone)]
pub struct ZipValidityIter<T, I, V>
where
I: Iterator<Item = T>,
V: Iterator<Item = bool>,
{
values: I,
validity: V,
}
impl<T, I, V> ZipValidityIter<T, I, V>
where
I: Iterator<Item = T>,
V: Iterator<Item = bool>,
{
pub fn new(values: I, validity: V) -> Self {
assert_eq!(values.size_hint(), validity.size_hint());
Self { values, validity }
}
}
impl<T, I, V> Iterator for ZipValidityIter<T, I, V>
where
I: Iterator<Item = T>,
V: Iterator<Item = bool>,
{
type Item = Option<T>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let value = self.values.next();
let is_valid = self.validity.next();
is_valid
.zip(value)
.map(|(is_valid, value)| is_valid.then(|| value))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.values.size_hint()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let value = self.values.nth(n);
let is_valid = self.validity.nth(n);
is_valid
.zip(value)
.map(|(is_valid, value)| is_valid.then(|| value))
}
}
impl<T, I, V> DoubleEndedIterator for ZipValidityIter<T, I, V>
where
I: DoubleEndedIterator<Item = T>,
V: DoubleEndedIterator<Item = bool>,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
let value = self.values.next_back();
let is_valid = self.validity.next_back();
is_valid
.zip(value)
.map(|(is_valid, value)| is_valid.then(|| value))
}
}
unsafe impl<T, I, V> TrustedLen for ZipValidityIter<T, I, V>
where
I: TrustedLen<Item = T>,
V: TrustedLen<Item = bool>,
{
}
impl<T, I, V> ExactSizeIterator for ZipValidityIter<T, I, V>
where
I: ExactSizeIterator<Item = T>,
V: ExactSizeIterator<Item = bool>,
{
}
#[derive(Debug, Clone)]
pub enum ZipValidity<T, I, V>
where
I: Iterator<Item = T>,
V: Iterator<Item = bool>,
{
Required(I),
Optional(ZipValidityIter<T, I, V>),
}
impl<T, I, V> ZipValidity<T, I, V>
where
I: Iterator<Item = T>,
V: Iterator<Item = bool>,
{
pub fn new(values: I, validity: Option<V>) -> Self {
match validity {
Some(validity) => Self::Optional(ZipValidityIter::new(values, validity)),
_ => Self::Required(values),
}
}
}
impl<'a, T, I> ZipValidity<T, I, BitmapIter<'a>>
where
I: Iterator<Item = T>,
{
pub fn new_with_validity(values: I, validity: Option<&'a Bitmap>) -> Self {
match validity.and_then(|validity| (validity.unset_bits() > 0).then(|| validity.iter())) {
Some(validity) => Self::Optional(ZipValidityIter::new(values, validity)),
_ => Self::Required(values),
}
}
}
impl<T, I, V> Iterator for ZipValidity<T, I, V>
where
I: Iterator<Item = T>,
V: Iterator<Item = bool>,
{
type Item = Option<T>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Required(values) => values.next().map(Some),
Self::Optional(zipped) => zipped.next(),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
Self::Required(values) => values.size_hint(),
Self::Optional(zipped) => zipped.size_hint(),
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
match self {
Self::Required(values) => values.nth(n).map(Some),
Self::Optional(zipped) => zipped.nth(n),
}
}
}
impl<T, I, V> DoubleEndedIterator for ZipValidity<T, I, V>
where
I: DoubleEndedIterator<Item = T>,
V: DoubleEndedIterator<Item = bool>,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
match self {
Self::Required(values) => values.next_back().map(Some),
Self::Optional(zipped) => zipped.next_back(),
}
}
}
impl<T, I, V> ExactSizeIterator for ZipValidity<T, I, V>
where
I: ExactSizeIterator<Item = T>,
V: ExactSizeIterator<Item = bool>,
{
}
unsafe impl<T, I, V> TrustedLen for ZipValidity<T, I, V>
where
I: TrustedLen<Item = T>,
V: TrustedLen<Item = bool>,
{
}
impl<T, I, V> ZipValidity<T, I, V>
where
I: Iterator<Item = T>,
V: Iterator<Item = bool>,
{
pub fn unwrap_required(self) -> I {
match self {
ZipValidity::Required(i) => i,
_ => panic!("Could not 'unwrap_required'. 'ZipValidity' iterator has nulls."),
}
}
pub fn unwrap_optional(self) -> ZipValidityIter<T, I, V> {
match self {
ZipValidity::Optional(i) => i,
_ => panic!("Could not 'unwrap_optional'. 'ZipValidity' iterator has no nulls."),
}
}
}