use core_traits::{Binding, TypedValue};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RelResult<T> {
pub width: usize,
pub values: Vec<T>,
}
pub type StructuredRelResult = RelResult<Binding>;
impl<T> RelResult<T> {
pub fn empty(width: usize) -> RelResult<T> {
RelResult {
width,
values: Vec::new(),
}
}
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
pub fn row_count(&self) -> usize {
self.values.len() / self.width
}
pub fn rows(&self) -> ::std::slice::Chunks<'_, T> {
self.values.chunks(self.width)
}
pub fn row(&self, index: usize) -> Option<&[T]> {
let end = self.width * (index + 1);
if end > self.values.len() {
None
} else {
let start = self.width * index;
Some(&self.values[start..end])
}
}
}
#[test]
fn test_rel_result() {
let empty = StructuredRelResult::empty(3);
let unit = StructuredRelResult {
width: 1,
values: vec![TypedValue::Long(5).into()],
};
let two_by_two = StructuredRelResult {
width: 2,
values: vec![
TypedValue::Long(5).into(),
TypedValue::Boolean(true).into(),
TypedValue::Long(-2).into(),
TypedValue::Boolean(false).into(),
],
};
assert!(empty.is_empty());
assert!(!unit.is_empty());
assert!(!two_by_two.is_empty());
assert_eq!(empty.row_count(), 0);
assert_eq!(unit.row_count(), 1);
assert_eq!(two_by_two.row_count(), 2);
assert_eq!(empty.row(0), None);
assert_eq!(unit.row(1), None);
assert_eq!(two_by_two.row(2), None);
assert_eq!(
unit.row(0),
Some(vec![TypedValue::Long(5).into()].as_slice())
);
assert_eq!(
two_by_two.row(0),
Some(vec![TypedValue::Long(5).into(), TypedValue::Boolean(true).into()].as_slice())
);
assert_eq!(
two_by_two.row(1),
Some(
vec![
TypedValue::Long(-2).into(),
TypedValue::Boolean(false).into()
]
.as_slice()
)
);
let mut rr = two_by_two.rows();
assert_eq!(
rr.next(),
Some(vec![TypedValue::Long(5).into(), TypedValue::Boolean(true).into()].as_slice())
);
assert_eq!(
rr.next(),
Some(
vec![
TypedValue::Long(-2).into(),
TypedValue::Boolean(false).into()
]
.as_slice()
)
);
assert_eq!(rr.next(), None);
}
impl From<Vec<Vec<TypedValue>>> for RelResult<Binding> {
fn from(src: Vec<Vec<TypedValue>>) -> Self {
if src.is_empty() {
RelResult::empty(0)
} else {
let width = src.get(0).map(|r| r.len()).unwrap_or(0);
RelResult {
width,
values: src
.into_iter()
.flat_map(|r| r.into_iter().map(|v| v.into()))
.collect(),
}
}
}
}
pub struct SubvecIntoIterator<T> {
width: usize,
values: ::std::vec::IntoIter<T>,
}
impl<T> Iterator for SubvecIntoIterator<T> {
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
let result: Vec<_> = (&mut self.values).take(self.width).collect();
if result.is_empty() {
None
} else {
Some(result)
}
}
}
impl<T> IntoIterator for RelResult<T> {
type Item = Vec<T>;
type IntoIter = SubvecIntoIterator<T>;
fn into_iter(self) -> Self::IntoIter {
SubvecIntoIterator {
width: self.width,
values: self.values.into_iter(),
}
}
}