Skip to main content

hdf5_pure/datatype/
layout.rs

1use core::num::NonZeroUsize;
2
3use crate::{FormatError, datatype::byte_order::FixedWidthByteOrder};
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub struct FixedPointLayout {
7    pub signed: bool,
8    pub bit_offset: u16,
9    pub bit_precision: u16,
10}
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub struct FloatingPointLayout {
14    pub bit_offset: u16,
15    pub bit_precision: u16,
16    pub exponent_location: u8,
17    pub exponent_size: u8,
18    pub mantissa_location: u8,
19    pub mantissa_size: u8,
20    pub exponent_bias: u32,
21}
22
23impl FloatingPointLayout {
24    pub const IEEE754_BINARY32: Self = Self {
25        bit_offset: 0,
26        bit_precision: 32,
27        exponent_location: 23,
28        exponent_size: 8,
29        mantissa_location: 0,
30        mantissa_size: 23,
31        exponent_bias: 127,
32    };
33    pub const IEEE754_BINARY64: Self = Self {
34        bit_offset: 0,
35        bit_precision: 64,
36        exponent_location: 52,
37        exponent_size: 11,
38        mantissa_location: 0,
39        mantissa_size: 52,
40        exponent_bias: 1023,
41    };
42}
43
44/// The width of a numeric element in the standard layout: 1, 2, 4, or 8 bytes.
45#[derive(Clone, Copy, Debug, Eq, PartialEq)]
46pub(crate) enum StandardWidth {
47    OneByte,
48    TwoBytes,
49    FourBytes,
50    EightBytes,
51}
52
53impl StandardWidth {
54    pub(crate) const fn bits(self) -> u16 {
55        match self {
56            Self::OneByte => 8,
57            Self::TwoBytes => 16,
58            Self::FourBytes => 32,
59            Self::EightBytes => 64,
60        }
61    }
62}
63
64#[derive(Clone, Copy, Debug, Eq, PartialEq)]
65pub(crate) struct StandardNumericLayout {
66    pub(crate) width: StandardWidth,
67    pub(crate) order: FixedWidthByteOrder,
68}
69
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
71pub(crate) struct NumericElementSize(NonZeroUsize);
72
73impl NumericElementSize {
74    const MAX: usize = 8;
75
76    pub fn new(size: u32) -> Result<Self, FormatError> {
77        #[expect(
78            clippy::map_err_ignore,
79            reason = "The semantics are fully communicated through the format error"
80        )]
81        let size = usize::try_from(size).map_err(|_| FormatError::ValueTooLargeForPlatform {
82            value: size.into(),
83            target: "usize",
84        })?;
85
86        let size = NonZeroUsize::new(size).expect("parsed HDF5 datatypes are never zero-sized");
87
88        if size.get() > Self::MAX {
89            return Err(FormatError::NumericElementTooWide { size: size.get() });
90        }
91
92        Ok(Self(size))
93    }
94
95    pub(crate) const fn get(self) -> usize {
96        self.0.get()
97    }
98}