#[cfg(not(feature = "std"))]
use alloc::{format, string::String, vec::Vec};
use crate::error::FormatError;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Layout {
Compact {
size: u64,
},
Contiguous {
address: Option<u64>,
size: u64,
},
Chunked {
chunk_shape: Vec<u64>,
index: ChunkIndex,
},
Virtual,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ChunkIndex {
BTreeV1,
SingleChunk,
Implicit,
FixedArray,
ExtensibleArray,
BTreeV2,
}
impl ChunkIndex {
#[must_use]
pub const fn supports_inplace_append(self) -> bool {
matches!(self, ChunkIndex::ExtensibleArray)
}
pub(crate) fn from_layout(version: u8, index_type: Option<u8>) -> Result<Self, FormatError> {
Ok(match (version, index_type) {
(3, _) => ChunkIndex::BTreeV1,
(4, Some(1)) => ChunkIndex::SingleChunk,
(4, Some(2)) => ChunkIndex::Implicit,
(4, Some(3)) => ChunkIndex::FixedArray,
(4, Some(4)) => ChunkIndex::ExtensibleArray,
(4, Some(5)) => ChunkIndex::BTreeV2,
(v, idx) => {
return Err(FormatError::ChunkedReadError(format!(
"unrecognized chunk index (layout version={v}, index type={idx:?})"
)));
}
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Chunk {
pub offset: Vec<u64>,
pub address: u64,
pub storage_size: u64,
pub filter_mask: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Filter {
pub id: u16,
pub name: Option<String>,
pub is_optional: bool,
pub client_data: Vec<u32>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chunk_index_from_layout_maps_every_kind() {
assert_eq!(
ChunkIndex::from_layout(3, None).unwrap(),
ChunkIndex::BTreeV1
);
assert_eq!(
ChunkIndex::from_layout(3, Some(4)).unwrap(),
ChunkIndex::BTreeV1,
"v3 is always a v1 B-tree regardless of the index-type byte"
);
assert_eq!(
ChunkIndex::from_layout(4, Some(1)).unwrap(),
ChunkIndex::SingleChunk
);
assert_eq!(
ChunkIndex::from_layout(4, Some(2)).unwrap(),
ChunkIndex::Implicit
);
assert_eq!(
ChunkIndex::from_layout(4, Some(3)).unwrap(),
ChunkIndex::FixedArray
);
assert_eq!(
ChunkIndex::from_layout(4, Some(4)).unwrap(),
ChunkIndex::ExtensibleArray
);
assert_eq!(
ChunkIndex::from_layout(4, Some(5)).unwrap(),
ChunkIndex::BTreeV2
);
}
#[test]
fn chunk_index_from_layout_rejects_unknown() {
assert!(ChunkIndex::from_layout(4, Some(9)).is_err());
assert!(ChunkIndex::from_layout(4, None).is_err());
assert!(ChunkIndex::from_layout(2, Some(1)).is_err());
}
#[test]
fn only_extensible_array_supports_inplace_append() {
assert!(ChunkIndex::ExtensibleArray.supports_inplace_append());
for idx in [
ChunkIndex::BTreeV1,
ChunkIndex::SingleChunk,
ChunkIndex::Implicit,
ChunkIndex::FixedArray,
ChunkIndex::BTreeV2,
] {
assert!(!idx.supports_inplace_append());
}
}
}