///|
#derive(Eq, @debug.Debug)
pub(all) enum DataspaceKind {
Scalar
Simple
Null
}
///|
pub extend DataspaceKind with Eq::{not_equal, equal}
///|
pub extend DataspaceKind with @debug.Debug::{to_repr}
///|
#derive(@debug.Debug)
pub(all) struct Dataspace {
kind : DataspaceKind
dimensions : Array[UInt64]
maximum_dimensions : Array[UInt64]
}
///|
pub extend Dataspace with @debug.Debug::{to_repr}
///|
fn parse_dataspace_data(
data : Bytes,
length_size : Int32,
) -> Dataspace raise Hdf5Error {
let reader = Reader::new(data)
let version = reader.read_u8().to_int()
let kind = match version {
1 => {
let dimensionality = reader.read_u8().to_int()
let flags = reader.read_u8().to_int()
reader.skip(1 + 4)
let kind : DataspaceKind = if dimensionality == 0 {
Scalar
} else {
Simple
}
(kind, flags, dimensionality)
}
2 => {
let dimensionality = reader.read_u8().to_int()
let flags = reader.read_u8().to_int()
let kind = match reader.read_u8().to_int() {
0 => Scalar
1 => Simple
2 => Null
_ => raise InvalidField("invalid dataspace type")
}
(kind, flags, dimensionality)
}
_ => raise InvalidField("unsupported dataspace message version")
}
let (kind, flags, dimensionality) = kind
if kind == Null {
return { kind: Null, dimensions: [], maximum_dimensions: [], }
}
let dimensions : Array[UInt64] = []
for _ in 0.. Dataspace raise Hdf5Error {
guard message.msg_type == msg_dataspace else {
raise InvalidField("message is not a dataspace message")
}
parse_dataspace_data(message.data, length_size)
}
///|
pub fn Dataspace::element_count(self : Dataspace) -> Int64 raise Hdf5Error {
match self.kind {
Null => 0L
Scalar => 1L
Simple => {
let mut count = 1L
for dimension in self.dimensions {
guard dimension <= 0x7FFFFFFFUL else {
raise InvalidField("dataspace dimension is too large")
}
}
if self.dimensions.contains(0UL) {
return 0L
}
for dimension in self.dimensions {
let size = dimension.reinterpret_as_int64()
guard count <= 0x7FFFFFFFFFFFFFFFL / size else {
raise InvalidField("dataspace element count overflow")
}
count = count * size
}
count
}
}
}