use crate::format::messages::data_layout::LayoutClass;
use crate::format::messages::filter_pipeline::FilterDesc;
#[derive(Debug, Clone)]
pub struct DatasetCreate {
pub layout: LayoutClass,
pub chunk_dims: Option<Vec<u64>>,
pub chunk_opts: Option<u8>,
pub filters: Vec<FilterInfo>,
pub external_files: Vec<ExternalStorageInfo>,
pub virtual_mappings: Vec<VirtualMappingInfo>,
pub virtual_spatial_tree: bool,
pub fill_alloc_time: Option<u8>,
pub fill_time: Option<u8>,
pub fill_value_defined: bool,
pub fill_value: Option<Vec<u8>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FilterInfo {
pub id: u16,
pub name: String,
pub flags: u16,
pub params: Vec<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExternalStorageInfo {
pub name: String,
pub file_offset: u64,
pub size: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VirtualMappingInfo {
pub file_name: String,
pub dataset_name: String,
pub source_select: VirtualSelectionInfo,
pub virtual_select: VirtualSelectionInfo,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VirtualSelectionInfo {
All,
Points(Vec<Vec<u64>>),
Regular {
start: Vec<u64>,
stride: Vec<u64>,
count: Vec<u64>,
block: Vec<u64>,
},
Irregular(Vec<IrregularHyperslabBlockInfo>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IrregularHyperslabBlockInfo {
pub start: Vec<u64>,
pub block: Vec<u64>,
}
impl FilterInfo {
pub fn from_desc(desc: &FilterDesc) -> Self {
let name = match desc.id {
1 => "deflate".to_string(),
2 => "shuffle".to_string(),
3 => "fletcher32".to_string(),
4 => "szip".to_string(),
5 => "nbit".to_string(),
6 => "scaleoffset".to_string(),
_ => desc
.name
.clone()
.unwrap_or_else(|| format!("filter_{}", desc.id)),
};
Self {
id: desc.id,
name,
flags: desc.flags,
params: desc.client_data.clone(),
}
}
}
impl DatasetCreate {
pub fn from_dataset(ds: &crate::hl::dataset::Dataset) -> crate::Result<Self> {
let info = ds.info()?;
let filters: Vec<FilterInfo> = info
.filter_pipeline
.as_ref()
.map(|p| p.filters.iter().map(FilterInfo::from_desc).collect())
.unwrap_or_default();
let external_files = ds.external_storage_entries_with_info(&info)?;
let virtual_mappings = ds.virtual_mapping_infos_with_info(&info)?;
Ok(Self {
layout: info.layout.layout_class,
chunk_dims: info.layout.chunk_dims,
chunk_opts: info.layout.chunk_flags,
filters,
external_files,
virtual_mappings,
virtual_spatial_tree: false,
fill_alloc_time: info.fill_value.as_ref().map(|fill| fill.alloc_time),
fill_time: info.fill_value.as_ref().map(|fill| fill.fill_time),
fill_value_defined: info
.fill_value
.as_ref()
.map(|fill| fill.defined)
.unwrap_or(false),
fill_value: info.fill_value.and_then(|fill| fill.value),
})
}
pub fn is_chunked(&self) -> bool {
self.layout == LayoutClass::Chunked
}
pub fn is_compressed(&self) -> bool {
self.filters.iter().any(|f| f.id == 1 || f.id == 4) }
pub fn has_shuffle(&self) -> bool {
self.filters.iter().any(|f| f.id == 2)
}
pub fn deflate_level(&self) -> Option<u32> {
self.filters
.iter()
.find(|f| f.id == 1)
.and_then(|f| f.params.first().copied())
}
pub fn chunk_opts(&self) -> Option<u8> {
self.chunk_opts
}
pub fn set_chunk_opts(&mut self, opts: Option<u8>) {
self.chunk_opts = opts;
}
pub fn external_count(&self) -> usize {
self.external_files.len()
}
pub fn external(&self, index: usize) -> Option<&ExternalStorageInfo> {
self.external_files.get(index)
}
pub fn set_external<S: Into<String>>(&mut self, name: S, file_offset: u64, size: u64) {
self.external_files.push(ExternalStorageInfo {
name: name.into(),
file_offset,
size,
});
}
pub fn filter(&self, index: usize) -> Option<&FilterInfo> {
self.filters.get(index)
}
pub fn filter_by_id(&self, id: u16) -> Option<&FilterInfo> {
self.filters.iter().find(|filter| filter.id == id)
}
pub fn set_filter<S: Into<String>>(&mut self, id: u16, name: S, flags: u16, params: Vec<u32>) {
if let Some(filter) = self.filters.iter_mut().find(|filter| filter.id == id) {
*filter = FilterInfo {
id,
name: name.into(),
flags,
params,
};
} else {
self.filters.push(FilterInfo {
id,
name: name.into(),
flags,
params,
});
}
}
pub fn set_shuffle(&mut self) {
self.set_filter(2, "shuffle", 0, Vec::new());
}
pub fn set_nbit(&mut self) {
self.set_filter(5, "nbit", 0, Vec::new());
}
pub fn set_scaleoffset(&mut self, params: Vec<u32>) {
self.set_filter(6, "scaleoffset", 0, params);
}
pub fn set_fletcher32(&mut self) {
self.set_filter(3, "fletcher32", 0, Vec::new());
}
pub fn set_szip(&mut self, params: Vec<u32>) {
self.set_filter(4, "szip", 0, params);
}
pub fn filter_count(&self) -> usize {
self.filters.len()
}
pub fn virtual_count(&self) -> usize {
self.virtual_mappings.len()
}
pub fn set_virtual(&mut self, mapping: VirtualMappingInfo) {
self.virtual_mappings.push(mapping);
}
pub fn virtual_filename(&self, index: usize) -> Option<&str> {
self.virtual_mappings
.get(index)
.map(|mapping| mapping.file_name.as_str())
}
pub fn virtual_dsetname(&self, index: usize) -> Option<&str> {
self.virtual_mappings
.get(index)
.map(|mapping| mapping.dataset_name.as_str())
}
pub fn virtual_srcspace(&self, index: usize) -> Option<&VirtualSelectionInfo> {
self.virtual_mappings
.get(index)
.map(|mapping| &mapping.source_select)
}
pub fn virtual_vspace(&self, index: usize) -> Option<&VirtualSelectionInfo> {
self.virtual_mappings
.get(index)
.map(|mapping| &mapping.virtual_select)
}
pub fn virtual_spatial_tree(&self) -> bool {
self.virtual_spatial_tree
}
pub fn set_virtual_spatial_tree(&mut self, enabled: bool) {
self.virtual_spatial_tree = enabled;
}
pub fn set_alloc_time(&mut self, alloc_time: u8) {
self.fill_alloc_time = Some(alloc_time);
}
pub fn set_fill_value(&mut self, value: Option<Vec<u8>>) {
self.fill_value_defined = value.is_some();
self.fill_value = value;
}
}