hdf5_reader/messages/
fill_value.rs1use crate::error::{Error, Result};
8use crate::io::Cursor;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum FillTime {
13 IfSet,
15 Always,
17 Never,
19}
20
21#[derive(Debug, Clone)]
23pub struct FillValueMessage {
24 pub defined: bool,
26 pub fill_time: FillTime,
28 pub value: Option<Vec<u8>>,
30}
31
32pub fn parse_old(
36 cursor: &mut Cursor<'_>,
37 _offset_size: u8,
38 _length_size: u8,
39 msg_size: usize,
40) -> Result<FillValueMessage> {
41 let value = if msg_size > 0 {
42 Some(cursor.read_bytes(msg_size)?.to_vec())
43 } else {
44 None
45 };
46
47 Ok(FillValueMessage {
48 defined: value.is_some(),
49 fill_time: FillTime::IfSet,
50 value,
51 })
52}
53
54pub fn parse_new(
56 cursor: &mut Cursor<'_>,
57 _offset_size: u8,
58 _length_size: u8,
59 msg_size: usize,
60) -> Result<FillValueMessage> {
61 let start = cursor.position();
62 let version = cursor.read_u8()?;
63
64 match version {
65 1 | 2 => parse_new_v1_v2(cursor, version),
66 3 => parse_new_v3(cursor),
67 v => Err(Error::UnsupportedFillValueVersion(v)),
68 }
69 .and_then(|msg| {
70 let consumed = (cursor.position() - start) as usize;
71 if consumed < msg_size {
72 cursor.skip(msg_size - consumed)?;
73 }
74 Ok(msg)
75 })
76}
77
78fn parse_new_v1_v2(cursor: &mut Cursor<'_>, _version: u8) -> Result<FillValueMessage> {
79 let _alloc_time = cursor.read_u8()?;
80 let fill_time_byte = cursor.read_u8()?;
81 let defined_flag = cursor.read_u8()?;
82
83 let fill_time = match fill_time_byte {
84 0 => FillTime::IfSet,
85 1 => FillTime::Always,
86 2 => FillTime::Never,
87 _ => FillTime::IfSet,
88 };
89
90 let defined = defined_flag != 0;
91
92 let value = if defined {
93 let size = cursor.read_u32_le()? as usize;
94 if size > 0 {
95 Some(cursor.read_bytes(size)?.to_vec())
96 } else {
97 None
98 }
99 } else {
100 None
101 };
102
103 Ok(FillValueMessage {
104 defined,
105 fill_time,
106 value,
107 })
108}
109
110fn parse_new_v3(cursor: &mut Cursor<'_>) -> Result<FillValueMessage> {
111 let flags = cursor.read_u8()?;
112
113 let _alloc_time = flags & 0x03;
114 let fill_time_bits = (flags >> 2) & 0x03;
115 let undefined = (flags & 0x20) != 0;
116 let defined = (flags & 0x10) != 0;
117
118 let fill_time = match fill_time_bits {
119 0 => FillTime::IfSet,
120 1 => FillTime::Always,
121 2 => FillTime::Never,
122 _ => FillTime::IfSet,
123 };
124
125 if undefined {
126 return Ok(FillValueMessage {
127 defined: false,
128 fill_time,
129 value: None,
130 });
131 }
132
133 let value = if defined {
134 let size = cursor.read_u32_le()? as usize;
135 if size > 0 {
136 Some(cursor.read_bytes(size)?.to_vec())
137 } else {
138 None
139 }
140 } else {
141 None
142 };
143
144 Ok(FillValueMessage {
145 defined,
146 fill_time,
147 value,
148 })
149}
150
151#[cfg(test)]
152mod tests {
153 use super::*;
154
155 #[test]
156 fn test_parse_old_fill() {
157 let data = [0x01, 0x02, 0x03, 0x04];
158 let mut cursor = Cursor::new(&data);
159 let msg = parse_old(&mut cursor, 8, 8, 4).unwrap();
160 assert!(msg.defined);
161 assert_eq!(msg.value.unwrap(), vec![0x01, 0x02, 0x03, 0x04]);
162 }
163
164 #[test]
165 fn test_parse_old_fill_empty() {
166 let data = [];
167 let mut cursor = Cursor::new(&data);
168 let msg = parse_old(&mut cursor, 8, 8, 0).unwrap();
169 assert!(!msg.defined);
170 assert!(msg.value.is_none());
171 }
172
173 #[test]
174 fn test_parse_new_v2_defined() {
175 let mut data = vec![
176 0x02, 0x01, 0x01, 0x01, ];
181 data.extend_from_slice(&8u32.to_le_bytes());
183 data.extend_from_slice(&[0xFF; 8]);
185
186 let mut cursor = Cursor::new(&data);
187 let msg = parse_new(&mut cursor, 8, 8, data.len()).unwrap();
188 assert!(msg.defined);
189 assert_eq!(msg.fill_time, FillTime::Always);
190 assert_eq!(msg.value.unwrap(), vec![0xFF; 8]);
191 }
192
193 #[test]
194 fn test_parse_new_v3_undefined() {
195 let data = [
196 0x03, 0x20, ];
199 let mut cursor = Cursor::new(&data);
200 let msg = parse_new(&mut cursor, 8, 8, data.len()).unwrap();
201 assert!(!msg.defined);
202 assert!(msg.value.is_none());
203 }
204}