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, Copy, PartialEq, Eq)]
pub struct FilterInfoRef<'a> {
pub id: u16,
pub name: &'a str,
pub flags: u16,
pub params: &'a [u32],
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExternalStorageInfo {
pub name: String,
pub file_offset: u64,
pub size: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExternalStorageInfoRef<'a> {
pub name: &'a str,
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, Copy, PartialEq, Eq)]
pub struct VirtualMappingInfoRef<'a> {
pub file_name: &'a str,
pub dataset_name: &'a str,
pub source_select: VirtualSelectionInfoRef<'a>,
pub virtual_select: VirtualSelectionInfoRef<'a>,
}
#[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, Copy, PartialEq, Eq)]
pub enum VirtualSelectionInfoRef<'a> {
All,
Points(&'a [Vec<u64>]),
Regular {
start: &'a [u64],
stride: &'a [u64],
count: &'a [u64],
block: &'a [u64],
},
Irregular(&'a [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(),
}
}
pub fn from_desc_owned(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.unwrap_or_else(|| format!("filter_{}", desc.id)),
};
Self {
id: desc.id,
name,
flags: desc.flags,
params: desc.client_data,
}
}
pub fn as_view(&self) -> FilterInfoRef<'_> {
FilterInfoRef {
id: self.id,
name: self.name.as_str(),
flags: self.flags,
params: self.params.as_slice(),
}
}
}
impl ExternalStorageInfo {
pub fn as_view(&self) -> ExternalStorageInfoRef<'_> {
ExternalStorageInfoRef {
name: self.name.as_str(),
file_offset: self.file_offset,
size: self.size,
}
}
}
impl VirtualMappingInfo {
pub fn as_view(&self) -> VirtualMappingInfoRef<'_> {
VirtualMappingInfoRef {
file_name: self.file_name.as_str(),
dataset_name: self.dataset_name.as_str(),
source_select: self.source_select.as_view(),
virtual_select: self.virtual_select.as_view(),
}
}
}
impl VirtualSelectionInfo {
pub fn as_view(&self) -> VirtualSelectionInfoRef<'_> {
match self {
Self::All => VirtualSelectionInfoRef::All,
Self::Points(points) => VirtualSelectionInfoRef::Points(points.as_slice()),
Self::Regular {
start,
stride,
count,
block,
} => VirtualSelectionInfoRef::Regular {
start: start.as_slice(),
stride: stride.as_slice(),
count: count.as_slice(),
block: block.as_slice(),
},
Self::Irregular(blocks) => VirtualSelectionInfoRef::Irregular(blocks.as_slice()),
}
}
}
impl DatasetCreate {
pub fn from_dataset(ds: &crate::hl::dataset::Dataset) -> crate::Result<Self> {
let info = ds.info()?;
let mut out = Self {
layout: info.layout.layout_class,
chunk_dims: None,
chunk_opts: None,
filters: Vec::new(),
external_files: Vec::new(),
virtual_mappings: Vec::new(),
virtual_spatial_tree: false,
fill_alloc_time: None,
fill_time: None,
fill_value_defined: false,
fill_value: None,
};
Self::from_dataset_info_into(ds, info, &mut out)?;
Ok(out)
}
pub fn from_dataset_into(
ds: &crate::hl::dataset::Dataset,
out: &mut Self,
) -> crate::Result<()> {
let info = ds.info()?;
Self::from_dataset_info_into(ds, info, out)
}
fn from_dataset_info_into(
ds: &crate::hl::dataset::Dataset,
info: crate::hl::dataset::DatasetInfo,
out: &mut Self,
) -> crate::Result<()> {
ds.external_storage_entries_with_info_into(&info, &mut out.external_files)?;
ds.virtual_mapping_infos_with_info_into(&info, &mut out.virtual_mappings)?;
out.filters.clear();
if let Some(pipeline) = info.filter_pipeline {
out.filters.reserve(pipeline.filters.len());
out.filters.extend(
pipeline
.filters
.into_iter()
.map(FilterInfo::from_desc_owned),
);
}
out.layout = info.layout.layout_class;
out.chunk_dims = info.layout.chunk_dims;
out.chunk_opts = info.layout.chunk_flags;
out.virtual_spatial_tree = false;
out.fill_alloc_time = info.fill_value.as_ref().map(|fill| fill.alloc_time);
out.fill_time = info.fill_value.as_ref().map(|fill| fill.fill_time);
out.fill_value_defined = info
.fill_value
.as_ref()
.map(|fill| fill.defined)
.unwrap_or(false);
out.fill_value = info.fill_value.and_then(|fill| fill.value);
Ok(())
}
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 chunk_dims(&self) -> Option<&[u64]> {
self.chunk_dims.as_deref()
}
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 external_entry(&self, index: usize) -> Option<ExternalStorageInfoRef<'_>> {
self.external(index).map(ExternalStorageInfo::as_view)
}
pub fn external_entries(&self) -> impl Iterator<Item = ExternalStorageInfoRef<'_>> {
self.external_files.iter().map(ExternalStorageInfo::as_view)
}
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_entry(&self, index: usize) -> Option<FilterInfoRef<'_>> {
self.filter(index).map(FilterInfo::as_view)
}
pub fn filter_entries(&self) -> impl Iterator<Item = FilterInfoRef<'_>> {
self.filters.iter().map(FilterInfo::as_view)
}
pub fn filter_by_id(&self, id: u16) -> Option<&FilterInfo> {
self.filters.iter().find(|filter| filter.id == id)
}
pub fn filter_entry_by_id(&self, id: u16) -> Option<FilterInfoRef<'_>> {
self.filter_by_id(id).map(FilterInfo::as_view)
}
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_mapping_entries(&self) -> impl Iterator<Item = VirtualMappingInfoRef<'_>> {
self.virtual_mappings
.iter()
.map(VirtualMappingInfo::as_view)
}
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_srcspace_view(&self, index: usize) -> Option<VirtualSelectionInfoRef<'_>> {
self.virtual_srcspace(index)
.map(VirtualSelectionInfo::as_view)
}
pub fn virtual_vspace(&self, index: usize) -> Option<&VirtualSelectionInfo> {
self.virtual_mappings
.get(index)
.map(|mapping| &mapping.virtual_select)
}
pub fn virtual_vspace_view(&self, index: usize) -> Option<VirtualSelectionInfoRef<'_>> {
self.virtual_vspace(index)
.map(VirtualSelectionInfo::as_view)
}
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;
}
pub fn fill_value(&self) -> Option<&[u8]> {
self.fill_value.as_deref()
}
}