use std::fmt::{self, Debug};
use std::ops::Deref;
use bitflags::bitflags;
#[cfg(hdf5_1_10_1)]
use hdf5_sys::h5f::H5F_fspace_strategy_t;
use hdf5_sys::h5o::{
H5O_SHMESG_ALL_FLAG, H5O_SHMESG_ATTR_FLAG, H5O_SHMESG_DTYPE_FLAG, H5O_SHMESG_FILL_FLAG,
H5O_SHMESG_NONE_FLAG, H5O_SHMESG_PLINE_FLAG, H5O_SHMESG_SDSPACE_FLAG,
};
use hdf5_sys::h5p::{
H5Pcreate, H5Pget_istore_k, H5Pget_shared_mesg_index, H5Pget_shared_mesg_nindexes,
H5Pget_shared_mesg_phase_change, H5Pget_sizes, H5Pget_sym_k, H5Pget_userblock, H5Pset_istore_k,
H5Pset_shared_mesg_index, H5Pset_shared_mesg_nindexes, H5Pset_shared_mesg_phase_change,
H5Pset_sym_k, H5Pset_userblock,
};
#[cfg(hdf5_1_10_1)]
use hdf5_sys::h5p::{
H5Pget_file_space_page_size, H5Pget_file_space_strategy, H5Pset_file_space_page_size,
H5Pset_file_space_strategy,
};
use crate::globals::H5P_FILE_CREATE;
use crate::internal_prelude::*;
#[repr(transparent)]
#[derive(Clone)]
pub struct FileCreate(Handle);
impl ObjectClass for FileCreate {
const NAME: &'static str = "file create property list";
const VALID_TYPES: &'static [H5I_type_t] = &[H5I_GENPROP_LST];
fn from_handle(handle: Handle) -> Self {
Self(handle)
}
fn handle(&self) -> &Handle {
&self.0
}
fn validate(&self) -> Result<()> {
let class = self.class()?;
if class != PropertyListClass::FileCreate {
fail!("expected file create property list, got {:?}", class);
}
Ok(())
}
}
impl Debug for FileCreate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let _e = silence_errors();
let mut formatter = f.debug_struct("FileCreate");
formatter
.field("userblock", &self.userblock())
.field("sizes", &self.sizes())
.field("sym_k", &self.sym_k())
.field("istore_k", &self.istore_k())
.field("shared_mesg_phase_change", &self.shared_mesg_phase_change())
.field("shared_mesg_indexes", &self.shared_mesg_indexes());
#[cfg(hdf5_1_10_1)]
{
formatter
.field("file_space_page_size", &self.file_space_page_size())
.field("file_space_strategy", &self.file_space_strategy());
}
formatter.finish()
}
}
impl Deref for FileCreate {
type Target = PropertyList;
fn deref(&self) -> &PropertyList {
unsafe { self.transmute() }
}
}
impl PartialEq for FileCreate {
fn eq(&self, other: &Self) -> bool {
<PropertyList as PartialEq>::eq(self, other)
}
}
impl Eq for FileCreate {}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct SizeofInfo {
pub sizeof_addr: usize,
pub sizeof_size: usize,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct SymbolTableInfo {
pub tree_rank: u32,
pub node_size: u32,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct PhaseChangeInfo {
pub max_list: u32,
pub min_btree: u32,
}
bitflags! {
pub struct SharedMessageType: u32 {
const NONE = H5O_SHMESG_NONE_FLAG;
const SIMPLE_DATASPACE = H5O_SHMESG_SDSPACE_FLAG;
const DATATYPE = H5O_SHMESG_DTYPE_FLAG;
const FILL_VALUE = H5O_SHMESG_FILL_FLAG;
const FILTER_PIPELINE = H5O_SHMESG_PLINE_FLAG;
const ATTRIBUTE = H5O_SHMESG_ATTR_FLAG;
const ALL = H5O_SHMESG_ALL_FLAG;
}
}
impl Default for SharedMessageType {
fn default() -> Self {
Self::NONE
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct SharedMessageIndex {
pub message_types: SharedMessageType,
pub min_message_size: u32,
}
#[cfg(hdf5_1_10_1)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum FileSpaceStrategy {
FreeSpaceManager {
paged: bool,
persist: bool,
threshold: u64,
},
PageAggregation,
None,
}
#[cfg(hdf5_1_10_1)]
impl Default for FileSpaceStrategy {
fn default() -> Self {
Self::FreeSpaceManager { paged: false, persist: false, threshold: 1 }
}
}
#[derive(Clone, Debug, Default)]
pub struct FileCreateBuilder {
userblock: Option<u64>,
sym_k: Option<SymbolTableInfo>,
istore_k: Option<u32>,
shared_mesg_phase_change: Option<PhaseChangeInfo>,
shared_mesg_indexes: Option<Vec<SharedMessageIndex>>,
#[cfg(hdf5_1_10_1)]
file_space_page_size: Option<u64>,
#[cfg(hdf5_1_10_1)]
file_space_strategy: Option<FileSpaceStrategy>,
}
impl FileCreateBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn from_plist(plist: &FileCreate) -> Result<Self> {
let mut builder = Self::default();
builder.userblock(plist.get_userblock()?);
let v = plist.get_sym_k()?;
builder.sym_k(v.tree_rank, v.node_size);
builder.istore_k(plist.get_istore_k()?);
let v = plist.get_shared_mesg_phase_change()?;
builder.shared_mesg_phase_change(v.max_list, v.min_btree);
builder.shared_mesg_indexes(&plist.get_shared_mesg_indexes()?);
#[cfg(hdf5_1_10_1)]
{
builder.file_space_page_size(plist.get_file_space_page_size()?);
builder.file_space_strategy(plist.get_file_space_strategy()?);
}
Ok(builder)
}
pub fn userblock(&mut self, size: u64) -> &mut Self {
self.userblock = Some(size);
self
}
pub fn sym_k(&mut self, tree_rank: u32, node_size: u32) -> &mut Self {
self.sym_k = Some(SymbolTableInfo { tree_rank, node_size });
self
}
pub fn istore_k(&mut self, ik: u32) -> &mut Self {
self.istore_k = Some(ik);
self
}
pub fn shared_mesg_phase_change(&mut self, max_list: u32, min_btree: u32) -> &mut Self {
self.shared_mesg_phase_change = Some(PhaseChangeInfo { max_list, min_btree });
self
}
pub fn shared_mesg_indexes(&mut self, indexes: &[SharedMessageIndex]) -> &mut Self {
self.shared_mesg_indexes = Some(indexes.into());
self
}
#[cfg(hdf5_1_10_1)]
pub fn file_space_page_size(&mut self, fsp_size: u64) -> &mut Self {
self.file_space_page_size = Some(fsp_size);
self
}
#[cfg(hdf5_1_10_1)]
pub fn file_space_strategy(&mut self, strategy: FileSpaceStrategy) -> &mut Self {
self.file_space_strategy = Some(strategy);
self
}
fn populate_plist(&self, id: hid_t) -> Result<()> {
if let Some(v) = self.userblock {
h5try!(H5Pset_userblock(id, v as _));
}
if let Some(v) = self.sym_k {
h5try!(H5Pset_sym_k(id, v.tree_rank as _, v.node_size as _));
}
if let Some(v) = self.istore_k {
h5try!(H5Pset_istore_k(id, v as _));
}
if let Some(v) = self.shared_mesg_phase_change {
h5try!(H5Pset_shared_mesg_phase_change(id, v.max_list as _, v.min_btree as _));
}
if let Some(ref v) = self.shared_mesg_indexes {
h5try!(H5Pset_shared_mesg_nindexes(id, v.len() as _));
for (i, v) in v.iter().enumerate() {
h5try!(H5Pset_shared_mesg_index(
id,
i as _,
v.message_types.bits() as _,
v.min_message_size as _,
));
}
}
#[cfg(hdf5_1_10_1)]
{
if let Some(v) = self.file_space_page_size {
h5try!(H5Pset_file_space_page_size(id, v as _));
}
if let Some(v) = self.file_space_strategy {
let (strategy, persist, threshold) = match v {
FileSpaceStrategy::FreeSpaceManager { paged, persist, threshold } => {
let strategy = if paged {
H5F_fspace_strategy_t::H5F_FSPACE_STRATEGY_PAGE
} else {
H5F_fspace_strategy_t::H5F_FSPACE_STRATEGY_FSM_AGGR
};
(strategy, persist as _, threshold as _)
}
FileSpaceStrategy::PageAggregation => {
(H5F_fspace_strategy_t::H5F_FSPACE_STRATEGY_AGGR, 0, 0)
}
_ => (H5F_fspace_strategy_t::H5F_FSPACE_STRATEGY_NONE, 0, 0),
};
h5try!(H5Pset_file_space_strategy(id, strategy, persist, threshold));
}
}
Ok(())
}
pub fn finish(&self) -> Result<FileCreate> {
h5lock!({
let plist = FileCreate::try_new()?;
self.populate_plist(plist.id())?;
Ok(plist)
})
}
}
impl FileCreate {
pub fn try_new() -> Result<Self> {
Self::from_id(h5try!(H5Pcreate(*H5P_FILE_CREATE)))
}
pub fn copy(&self) -> Self {
unsafe { self.deref().copy().cast() }
}
pub fn build() -> FileCreateBuilder {
FileCreateBuilder::new()
}
#[doc(hidden)]
pub fn get_userblock(&self) -> Result<u64> {
h5get!(H5Pget_userblock(self.id()): hsize_t).map(|x| x as _)
}
#[doc(hidden)]
pub fn get_sizes(&self) -> Result<SizeofInfo> {
h5get!(H5Pget_sizes(self.id()): size_t, size_t).map(|(sizeof_addr, sizeof_size)| {
SizeofInfo { sizeof_addr: sizeof_addr as _, sizeof_size: sizeof_size as _ }
})
}
#[doc(hidden)]
pub fn get_sym_k(&self) -> Result<SymbolTableInfo> {
h5get!(H5Pget_sym_k(self.id()): c_uint, c_uint).map(|(tree_rank, node_size)| {
SymbolTableInfo { tree_rank: tree_rank as _, node_size: node_size as _ }
})
}
#[doc(hidden)]
pub fn get_istore_k(&self) -> Result<u32> {
h5get!(H5Pget_istore_k(self.id()): c_uint).map(|x| x as _)
}
#[doc(hidden)]
pub fn get_shared_mesg_phase_change(&self) -> Result<PhaseChangeInfo> {
h5get!(H5Pget_shared_mesg_phase_change(self.id()): c_uint, c_uint).map(
|(max_list, min_btree)| PhaseChangeInfo {
max_list: max_list as _,
min_btree: min_btree as _,
},
)
}
#[doc(hidden)]
pub fn get_shared_mesg_indexes(&self) -> Result<Vec<SharedMessageIndex>> {
let n = h5get_d!(H5Pget_shared_mesg_nindexes(self.id()): c_uint);
let mut indexes = Vec::with_capacity(n as _);
for i in 0..n {
let (mut flags, mut min_size): (c_uint, c_uint) = (0, 0);
h5try!(H5Pget_shared_mesg_index(self.id(), i, &mut flags, &mut min_size));
indexes.push(SharedMessageIndex {
message_types: SharedMessageType::from_bits_truncate(flags as _),
min_message_size: min_size as _,
});
}
Ok(indexes)
}
#[doc(hidden)]
#[cfg(hdf5_1_10_1)]
pub fn get_file_space_page_size(&self) -> Result<u64> {
h5get!(H5Pget_file_space_page_size(self.id()): hsize_t).map(|x| x as _)
}
#[doc(hidden)]
#[cfg(hdf5_1_10_1)]
pub fn get_file_space_strategy(&self) -> Result<FileSpaceStrategy> {
let (strategy, persist, threshold) =
h5get!(H5Pget_file_space_strategy(self.id()): H5F_fspace_strategy_t, hbool_t, hsize_t)?;
Ok(match strategy {
H5F_fspace_strategy_t::H5F_FSPACE_STRATEGY_FSM_AGGR => {
FileSpaceStrategy::FreeSpaceManager {
paged: false,
persist: persist != 0,
threshold: threshold as _,
}
}
H5F_fspace_strategy_t::H5F_FSPACE_STRATEGY_PAGE => {
FileSpaceStrategy::FreeSpaceManager {
paged: true,
persist: persist != 0,
threshold: threshold as _,
}
}
H5F_fspace_strategy_t::H5F_FSPACE_STRATEGY_AGGR => FileSpaceStrategy::PageAggregation,
_ => FileSpaceStrategy::None,
})
}
pub fn userblock(&self) -> u64 {
self.get_userblock().unwrap_or(0)
}
pub fn sizes(&self) -> SizeofInfo {
self.get_sizes().unwrap_or_else(|_| SizeofInfo::default())
}
pub fn sym_k(&self) -> SymbolTableInfo {
self.get_sym_k().unwrap_or_else(|_| SymbolTableInfo::default())
}
pub fn istore_k(&self) -> u32 {
self.get_istore_k().unwrap_or(0)
}
pub fn shared_mesg_phase_change(&self) -> PhaseChangeInfo {
self.get_shared_mesg_phase_change().unwrap_or_else(|_| PhaseChangeInfo::default())
}
pub fn shared_mesg_indexes(&self) -> Vec<SharedMessageIndex> {
self.get_shared_mesg_indexes().unwrap_or_else(|_| Vec::new())
}
#[cfg(hdf5_1_10_1)]
pub fn file_space_page_size(&self) -> u64 {
self.get_file_space_page_size().unwrap_or(0)
}
#[cfg(hdf5_1_10_1)]
pub fn file_space_strategy(&self) -> FileSpaceStrategy {
self.get_file_space_strategy().unwrap_or_else(|_| FileSpaceStrategy::default())
}
}