rust_hdf5/format/messages/
fill_value.rs1use crate::format::{FormatError, FormatResult};
11
12const VERSION: u8 = 3;
13
14#[derive(Debug, Clone, PartialEq)]
16pub struct FillValueMessage {
17 pub alloc_time: u8,
19 pub fill_write_time: u8,
21 pub fill_defined: u8,
23 pub fill_value: Option<Vec<u8>>,
25}
26
27impl Default for FillValueMessage {
28 fn default() -> Self {
29 Self {
30 alloc_time: 2, fill_write_time: 0, fill_defined: 1, fill_value: None,
34 }
35 }
36}
37
38impl FillValueMessage {
39 pub fn with_value(data: Vec<u8>) -> Self {
41 Self {
42 alloc_time: 2,
43 fill_write_time: 0,
44 fill_defined: 2,
45 fill_value: Some(data),
46 }
47 }
48
49 pub fn undefined() -> Self {
51 Self {
52 alloc_time: 2,
53 fill_write_time: 1, fill_defined: 0,
55 fill_value: None,
56 }
57 }
58
59 pub fn encode(&self) -> Vec<u8> {
62 let mut buf = Vec::with_capacity(8);
63 buf.push(VERSION);
64 buf.push(self.alloc_time);
65 buf.push(self.fill_write_time);
66 buf.push(self.fill_defined);
67
68 if self.fill_defined == 2 {
69 if let Some(ref data) = self.fill_value {
70 buf.extend_from_slice(&(data.len() as u32).to_le_bytes());
71 buf.extend_from_slice(data);
72 } else {
73 buf.extend_from_slice(&0u32.to_le_bytes());
74 }
75 }
76
77 buf
78 }
79
80 pub fn decode(buf: &[u8]) -> FormatResult<(Self, usize)> {
83 if buf.len() < 4 {
84 return Err(FormatError::BufferTooShort {
85 needed: 4,
86 available: buf.len(),
87 });
88 }
89
90 let version = buf[0];
91 if version != VERSION {
92 return Err(FormatError::InvalidVersion(version));
93 }
94
95 let alloc_time = buf[1];
96 let fill_write_time = buf[2];
97 let fill_defined = buf[3];
98
99 let mut pos = 4;
100 let fill_value = if fill_defined == 2 {
101 if buf.len() < pos + 4 {
102 return Err(FormatError::BufferTooShort {
103 needed: pos + 4,
104 available: buf.len(),
105 });
106 }
107 let size =
108 u32::from_le_bytes([buf[pos], buf[pos + 1], buf[pos + 2], buf[pos + 3]]) as usize;
109 pos += 4;
110 if buf.len() < pos + size {
111 return Err(FormatError::BufferTooShort {
112 needed: pos + size,
113 available: buf.len(),
114 });
115 }
116 let data = buf[pos..pos + size].to_vec();
117 pos += size;
118 Some(data)
119 } else {
120 None
121 };
122
123 Ok((
124 Self {
125 alloc_time,
126 fill_write_time,
127 fill_defined,
128 fill_value,
129 },
130 pos,
131 ))
132 }
133}
134
135#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn roundtrip_default() {
143 let msg = FillValueMessage::default();
144 let encoded = msg.encode();
145 assert_eq!(encoded.len(), 4);
146 let (decoded, consumed) = FillValueMessage::decode(&encoded).unwrap();
147 assert_eq!(consumed, 4);
148 assert_eq!(decoded, msg);
149 }
150
151 #[test]
152 fn roundtrip_user_defined() {
153 let msg = FillValueMessage::with_value(vec![0xDE, 0xAD, 0xBE, 0xEF]);
154 let encoded = msg.encode();
155 assert_eq!(encoded.len(), 12);
157 let (decoded, consumed) = FillValueMessage::decode(&encoded).unwrap();
158 assert_eq!(consumed, 12);
159 assert_eq!(decoded, msg);
160 assert_eq!(
161 decoded.fill_value.as_ref().unwrap(),
162 &vec![0xDE, 0xAD, 0xBE, 0xEF]
163 );
164 }
165
166 #[test]
167 fn roundtrip_undefined() {
168 let msg = FillValueMessage::undefined();
169 let encoded = msg.encode();
170 assert_eq!(encoded.len(), 4);
171 let (decoded, consumed) = FillValueMessage::decode(&encoded).unwrap();
172 assert_eq!(consumed, 4);
173 assert_eq!(decoded, msg);
174 }
175
176 #[test]
177 fn roundtrip_empty_user_data() {
178 let msg = FillValueMessage {
179 alloc_time: 1,
180 fill_write_time: 2,
181 fill_defined: 2,
182 fill_value: Some(vec![]),
183 };
184 let encoded = msg.encode();
185 assert_eq!(encoded.len(), 8);
187 let (decoded, consumed) = FillValueMessage::decode(&encoded).unwrap();
188 assert_eq!(consumed, 8);
189 assert_eq!(decoded, msg);
190 }
191
192 #[test]
193 fn decode_bad_version() {
194 let buf = [1u8, 2, 0, 1]; let err = FillValueMessage::decode(&buf).unwrap_err();
196 match err {
197 FormatError::InvalidVersion(1) => {}
198 other => panic!("unexpected error: {:?}", other),
199 }
200 }
201
202 #[test]
203 fn decode_buffer_too_short() {
204 let buf = [3u8, 2];
205 let err = FillValueMessage::decode(&buf).unwrap_err();
206 match err {
207 FormatError::BufferTooShort { .. } => {}
208 other => panic!("unexpected error: {:?}", other),
209 }
210 }
211
212 #[test]
213 fn decode_user_defined_truncated_size() {
214 let buf = [3u8, 2, 0, 2, 0xFF];
216 let err = FillValueMessage::decode(&buf).unwrap_err();
217 match err {
218 FormatError::BufferTooShort { .. } => {}
219 other => panic!("unexpected error: {:?}", other),
220 }
221 }
222
223 #[test]
224 fn decode_user_defined_truncated_data() {
225 let buf = [3u8, 2, 0, 2, 4, 0, 0, 0, 0xAA, 0xBB];
227 let err = FillValueMessage::decode(&buf).unwrap_err();
228 match err {
229 FormatError::BufferTooShort {
230 needed: 12,
231 available: 10,
232 } => {}
233 other => panic!("unexpected error: {:?}", other),
234 }
235 }
236
237 #[test]
238 fn version_byte() {
239 let encoded = FillValueMessage::default().encode();
240 assert_eq!(encoded[0], 3);
241 }
242}