use crate::db::schema::FieldId;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub(in crate::db) struct SchemaVersion(u32);
impl SchemaVersion {
#[must_use]
pub(in crate::db) const fn new(raw: u32) -> Self {
Self(raw)
}
#[must_use]
pub(in crate::db) const fn initial() -> Self {
Self(1)
}
#[must_use]
pub(in crate::db) const fn get(self) -> u32 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub(in crate::db) struct SchemaFieldSlot(u16);
impl SchemaFieldSlot {
#[must_use]
pub(in crate::db) const fn new(raw: u16) -> Self {
Self(raw)
}
#[must_use]
pub(in crate::db) fn from_generated_index(index: usize) -> Self {
let slot = u16::try_from(index).expect("schema layout invariant");
Self(slot)
}
#[must_use]
pub(in crate::db) const fn get(self) -> u16 {
self.0
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct SchemaRowLayout {
version: SchemaVersion,
field_to_slot: Vec<(FieldId, SchemaFieldSlot)>,
}
impl SchemaRowLayout {
#[must_use]
pub(in crate::db) const fn new(
version: SchemaVersion,
field_to_slot: Vec<(FieldId, SchemaFieldSlot)>,
) -> Self {
Self {
version,
field_to_slot,
}
}
#[must_use]
pub(in crate::db) const fn version(&self) -> SchemaVersion {
self.version
}
#[must_use]
pub(in crate::db) const fn field_to_slot(&self) -> &[(FieldId, SchemaFieldSlot)] {
self.field_to_slot.as_slice()
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_version(&self, version: SchemaVersion) -> Self {
Self::new(version, self.field_to_slot.clone())
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn next_unallocated_slot(&self) -> SchemaFieldSlot {
SchemaFieldSlot::from_generated_index(self.field_to_slot.len())
}
#[must_use]
pub(in crate::db) const fn allocated_slot_count(&self) -> usize {
self.field_to_slot.len()
}
#[must_use]
pub(in crate::db) fn slot_for_field(&self, field_id: FieldId) -> Option<SchemaFieldSlot> {
self.field_to_slot
.iter()
.find_map(|(id, slot)| (*id == field_id).then_some(*slot))
}
}