#[cfg(not(feature = "std"))]
use crate::nostd_prelude::*;
use super::{ColumnNames, PackedRow};
fn declared_columns<'a>(v: &'a crate::Value, names: &[Vec<u8>]) -> Option<Vec<Option<&'a [u8]>>> {
use kevy_bytes::SmallBytes;
let len = match v {
crate::Value::Hash(h) => h.len(),
crate::Value::SegHash(h) => h.len(),
crate::Value::SmallHashInline(h) => h.len(),
_ => return None,
};
if len > names.len() {
return None;
}
let cols: Vec<Option<&[u8]>> = match v {
crate::Value::Hash(h) => {
names.iter().map(|n| h.get(n.as_slice()).map(SmallBytes::as_slice)).collect()
}
crate::Value::SegHash(h) => {
names.iter().map(|n| h.get(n).map(SmallBytes::as_slice)).collect()
}
crate::Value::SmallHashInline(h) => names.iter().map(|n| h.get(n)).collect(),
_ => return None,
};
(cols.iter().flatten().count() == len).then_some(cols)
}
impl crate::Store {
#[doc(hidden)]
pub fn is_packed(&mut self, key: &[u8]) -> bool {
matches!(self.live_entry(key).map(|e| &e.value), Some(crate::Value::PackedRow(_)))
}
pub fn packed_rows_enabled(&self) -> bool {
self.packed_rows
}
pub fn set_packed_rows(&mut self, on: bool) {
self.packed_rows = on;
}
fn hot_general_hash(&mut self, key: &[u8]) -> bool {
matches!(
self.live_entry(key).map(|e| &e.value),
Some(
crate::Value::Hash(_) | crate::Value::SmallHashInline(_) | crate::Value::SegHash(_)
)
)
}
pub fn pack_row(&mut self, key: &[u8], names: &ColumnNames) {
if !self.hfttl.is_empty() {
if !self.hot_general_hash(key) {
if matches!(self.live_entry(key).map(|e| &e.value), Some(crate::Value::Cold(_))) {
self.share_shape(names);
}
return;
}
self.purge_hash_ttl(key);
}
let Some(e) = self.live_entry(key) else { return };
let cold = matches!(e.value, crate::Value::Cold(_));
let Some(row) = declared_columns(&e.value, names).and_then(|c| PackedRow::build(names, &c))
else {
if cold {
self.share_shape(names);
}
return;
};
self.share_shape(names);
if let Some(e) = self.live_entry_mut(key) {
e.value = crate::Value::PackedRow(row);
}
self.reweigh_entry(key);
}
pub(crate) fn share_shape(&mut self, names: &ColumnNames) {
if self.row_shapes.iter().any(|s| alloc::sync::Arc::ptr_eq(s, names)) {
return;
}
self.row_shapes.retain(|s| alloc::sync::Arc::strong_count(s) > 1);
self.row_shapes.push(names.clone());
}
}