use super::types::ScalarValue;
use hexane::{lebsize, ulebsize, PackError};
#[derive(Debug)]
pub(crate) enum ValueType {
Null,
False,
True,
Uleb,
Leb,
Float,
String,
Bytes,
Counter,
Timestamp,
Unknown(u8),
}
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub(crate) struct ValueMeta(u64);
impl ValueMeta {
pub(crate) fn type_code(&self) -> ValueType {
let low_byte = (self.0 as u8) & 0b00001111;
match low_byte {
0 => ValueType::Null,
1 => ValueType::False,
2 => ValueType::True,
3 => ValueType::Uleb,
4 => ValueType::Leb,
5 => ValueType::Float,
6 => ValueType::String,
7 => ValueType::Bytes,
8 => ValueType::Counter,
9 => ValueType::Timestamp,
other => ValueType::Unknown(other),
}
}
pub(crate) fn length(&self) -> usize {
(self.0 >> 4) as usize
}
}
impl From<u64> for ValueMeta {
fn from(raw: u64) -> Self {
ValueMeta(raw)
}
}
impl From<&crate::ScalarValue> for ValueMeta {
fn from(p: &crate::ScalarValue) -> Self {
match p {
crate::ScalarValue::Uint(i) => Self((ulebsize(*i) << 4) | 3),
crate::ScalarValue::Int(i) => Self((lebsize(*i) << 4) | 4),
crate::ScalarValue::Null => Self(0),
crate::ScalarValue::Boolean(b) => Self(match b {
false => 1,
true => 2,
}),
crate::ScalarValue::Timestamp(i) => Self((lebsize(*i) << 4) | 9),
crate::ScalarValue::F64(_) => Self((8 << 4) | 5),
crate::ScalarValue::Counter(i) => Self((lebsize(i.start) << 4) | 8),
crate::ScalarValue::Str(s) => Self(((s.len() as u64) << 4) | 6),
crate::ScalarValue::Bytes(b) => Self(((b.len() as u64) << 4) | 7),
crate::ScalarValue::Unknown { type_code, bytes } => {
Self(((bytes.len() as u64) << 4) | (*type_code as u64))
}
}
}
}
impl<'a> From<&'a ScalarValue<'a>> for ValueMeta {
fn from(p: &'a ScalarValue<'a>) -> Self {
match p {
ScalarValue::Uint(i) => Self((ulebsize(*i) << 4) | 3),
ScalarValue::Int(i) => Self((lebsize(*i) << 4) | 4),
ScalarValue::Null => Self(0),
ScalarValue::Boolean(b) => Self(match b {
false => 1,
true => 2,
}),
ScalarValue::Timestamp(i) => Self((lebsize(*i) << 4) | 9),
ScalarValue::F64(_) => Self((8 << 4) | 5),
ScalarValue::Counter(i) => Self((lebsize(*i) << 4) | 8),
ScalarValue::Str(s) => Self(((s.len() as u64) << 4) | 6),
ScalarValue::Bytes(b) => Self(((b.len() as u64) << 4) | 7),
ScalarValue::Unknown { type_code, bytes } => {
Self(((bytes.len() as u64) << 4) | (*type_code as u64))
}
}
}
}
impl From<&[u8]> for ValueMeta {
fn from(b: &[u8]) -> Self {
Self(((b.len() as u64) << 4) | 7)
}
}
impl hexane::ColumnValue for ValueMeta {
type Encoding<C: hexane::Codec> = hexane::RleEncoding<ValueMeta, C>;
}
impl hexane::RleValue for ValueMeta {
fn try_unpack<C: hexane::Codec>(data: &[u8]) -> Result<(usize, ValueMeta), PackError> {
let (n, v) = C::try_read_unsigned(data)?;
Ok((n, ValueMeta(v)))
}
fn pack<C: hexane::Codec>(value: ValueMeta, out: &mut Vec<u8>) -> bool {
out.extend(C::encode_unsigned(value.0));
true
}
}
impl hexane::PrefixValue for ValueMeta {
type Prefix = u64;
fn accumulate(target: &mut u64, val: ValueMeta) {
*target += val.length() as u64;
}
fn accumulate_run(target: &mut u64, run: &hexane::Run<ValueMeta>) {
*target += run.value.length() as u64 * run.count as u64;
}
}
#[cfg(test)]
mod tests {
use super::*;
use hexane::PrefixColumn;
#[test]
fn column_data_meta_group() {
let data = vec![
ValueMeta(1), ValueMeta(6 + (30 << 4)), ValueMeta(6 + (10 << 4)), ValueMeta(3), ValueMeta(4), ];
let col = PrefixColumn::<ValueMeta>::from_values(data);
let mut iter = col.iter();
let pv = iter.next().unwrap();
assert_eq!(pv.value, ValueMeta(1));
assert_eq!(pv.total(), 0);
let pv = iter.next().unwrap();
assert_eq!(pv.value, ValueMeta(6 + (30 << 4)));
assert_eq!(pv.total(), 30);
let pv = iter.next().unwrap();
assert_eq!(pv.value, ValueMeta(6 + (10 << 4)));
assert_eq!(pv.total(), 40);
let pv = iter.next().unwrap();
assert_eq!(pv.value, ValueMeta(3));
assert_eq!(pv.total(), 40);
let pv = col.iter().nth(3).unwrap();
assert_eq!(pv.value, ValueMeta(3));
assert_eq!(pv.total(), 40);
let mut iter = col.iter_range(3..5);
let pv = iter.next().unwrap();
assert_eq!(pv.value, ValueMeta(3));
assert_eq!(pv.total(), 40);
}
}