1use crate::codec::range_decoder::RangeDecoder;
2use crate::codec::range_encoder::RangeEncoder;
3use crate::decoder;
4use crate::encoder;
5use crate::error::{FpZipError, Result};
6use crate::header::{FpZipHeader, FpZipType};
7
8extern crate alloc;
9use alloc::vec;
10use alloc::vec::Vec;
11
12fn compress_f32_prec(
15 data: &[f32],
16 nx: u32,
17 ny: u32,
18 nz: u32,
19 nf: u32,
20 prec: u32,
21) -> Result<Vec<u8>> {
22 validate_dimensions(data.len(), nx, ny, nz, nf)?;
23
24 let mut header = FpZipHeader::new(FpZipType::Float, nx, ny, nz, nf);
25 let bits = if prec == 0 { 32 } else { prec };
29 header.prec = prec;
30 let mut enc = RangeEncoder::with_capacity(data.len() * 4);
31 header.write_to_encoder(&mut enc);
32 encoder::compress_4d_float(
33 &mut enc, data, nx as i32, ny as i32, nz as i32, nf as i32, bits,
34 );
35 Ok(enc.finish())
36}
37
38fn compress_f64_prec(
39 data: &[f64],
40 nx: u32,
41 ny: u32,
42 nz: u32,
43 nf: u32,
44 prec: u32,
45) -> Result<Vec<u8>> {
46 validate_dimensions(data.len(), nx, ny, nz, nf)?;
47
48 let mut header = FpZipHeader::new(FpZipType::Double, nx, ny, nz, nf);
49 let bits = if prec == 0 { 64 } else { prec };
50 header.prec = prec;
51 let mut enc = RangeEncoder::with_capacity(data.len() * 8);
52 header.write_to_encoder(&mut enc);
53 encoder::compress_4d_double(
54 &mut enc, data, nx as i32, ny as i32, nz as i32, nf as i32, bits,
55 );
56 Ok(enc.finish())
57}
58
59fn decompress_f32_impl(data: &[u8]) -> Result<(FpZipHeader, Vec<f32>)> {
60 let mut dec = RangeDecoder::new(data);
61 dec.init();
62
63 let header = FpZipHeader::read_from_decoder(&mut dec)?;
64 if header.data_type != FpZipType::Float {
65 return Err(FpZipError::TypeMismatch {
66 expected: FpZipType::Float,
67 actual: header.data_type,
68 });
69 }
70
71 let bits = if header.prec == 0 { 32 } else { header.prec };
72 let total = header.total_elements() as usize;
73 let mut result = vec![0.0f32; total];
74 decoder::decompress_4d_float(
75 &mut dec,
76 &mut result,
77 header.nx as i32,
78 header.ny as i32,
79 header.nz as i32,
80 header.nf as i32,
81 bits,
82 );
83 Ok((header, result))
84}
85
86fn decompress_f64_impl(data: &[u8]) -> Result<(FpZipHeader, Vec<f64>)> {
87 let mut dec = RangeDecoder::new(data);
88 dec.init();
89
90 let header = FpZipHeader::read_from_decoder(&mut dec)?;
91 if header.data_type != FpZipType::Double {
92 return Err(FpZipError::TypeMismatch {
93 expected: FpZipType::Double,
94 actual: header.data_type,
95 });
96 }
97
98 let bits = if header.prec == 0 { 64 } else { header.prec };
99 let total = header.total_elements() as usize;
100 let mut result = vec![0.0f64; total];
101 decoder::decompress_4d_double(
102 &mut dec,
103 &mut result,
104 header.nx as i32,
105 header.ny as i32,
106 header.nz as i32,
107 header.nf as i32,
108 bits,
109 );
110 Ok((header, result))
111}
112
113pub fn compress_f32(data: &[f32], nx: u32, ny: u32, nz: u32, nf: u32) -> Result<Vec<u8>> {
127 compress_f32_prec(data, nx, ny, nz, nf, 32)
128}
129
130pub fn compress_f64(data: &[f64], nx: u32, ny: u32, nz: u32, nf: u32) -> Result<Vec<u8>> {
134 compress_f64_prec(data, nx, ny, nz, nf, 64)
135}
136
137pub fn decompress_f32(data: &[u8]) -> Result<Vec<f32>> {
144 decompress_f32_impl(data).map(|(_, v)| v)
145}
146
147pub fn decompress_f64(data: &[u8]) -> Result<Vec<f64>> {
151 decompress_f64_impl(data).map(|(_, v)| v)
152}
153
154pub fn decompress_f32_into(data: &[u8], output: &mut [f32]) -> Result<FpZipHeader> {
159 let mut dec = RangeDecoder::new(data);
160 dec.init();
161
162 let header = FpZipHeader::read_from_decoder(&mut dec)?;
163 if header.data_type != FpZipType::Float {
164 return Err(FpZipError::TypeMismatch {
165 expected: FpZipType::Float,
166 actual: header.data_type,
167 });
168 }
169
170 let bits = if header.prec == 0 { 32 } else { header.prec };
171 let total = header.total_elements() as usize;
172 if output.len() < total {
173 return Err(FpZipError::BufferTooSmall {
174 needed: total,
175 available: output.len(),
176 });
177 }
178 decoder::decompress_4d_float(
179 &mut dec,
180 output,
181 header.nx as i32,
182 header.ny as i32,
183 header.nz as i32,
184 header.nf as i32,
185 bits,
186 );
187 Ok(header)
188}
189
190pub fn decompress_f64_into(data: &[u8], output: &mut [f64]) -> Result<FpZipHeader> {
194 let mut dec = RangeDecoder::new(data);
195 dec.init();
196
197 let header = FpZipHeader::read_from_decoder(&mut dec)?;
198 if header.data_type != FpZipType::Double {
199 return Err(FpZipError::TypeMismatch {
200 expected: FpZipType::Double,
201 actual: header.data_type,
202 });
203 }
204
205 let bits = if header.prec == 0 { 64 } else { header.prec };
206 let total = header.total_elements() as usize;
207 if output.len() < total {
208 return Err(FpZipError::BufferTooSmall {
209 needed: total,
210 available: output.len(),
211 });
212 }
213 decoder::decompress_4d_double(
214 &mut dec,
215 output,
216 header.nx as i32,
217 header.ny as i32,
218 header.nz as i32,
219 header.nf as i32,
220 bits,
221 );
222 Ok(header)
223}
224
225pub fn compress_f32_into(
232 data: &[f32],
233 destination: &mut [u8],
234 nx: u32,
235 ny: u32,
236 nz: u32,
237 nf: u32,
238) -> Result<usize> {
239 let compressed = compress_f32(data, nx, ny, nz, nf)?;
240 if compressed.len() > destination.len() {
241 return Err(FpZipError::BufferTooSmall {
242 needed: compressed.len(),
243 available: destination.len(),
244 });
245 }
246 destination[..compressed.len()].copy_from_slice(&compressed);
247 Ok(compressed.len())
248}
249
250pub fn compress_f64_into(
254 data: &[f64],
255 destination: &mut [u8],
256 nx: u32,
257 ny: u32,
258 nz: u32,
259 nf: u32,
260) -> Result<usize> {
261 let compressed = compress_f64(data, nx, ny, nz, nf)?;
262 if compressed.len() > destination.len() {
263 return Err(FpZipError::BufferTooSmall {
264 needed: compressed.len(),
265 available: destination.len(),
266 });
267 }
268 destination[..compressed.len()].copy_from_slice(&compressed);
269 Ok(compressed.len())
270}
271
272pub fn read_header(data: &[u8]) -> Result<FpZipHeader> {
276 let mut dec = RangeDecoder::new(data);
277 dec.init();
278 FpZipHeader::read_from_decoder(&mut dec)
279}
280
281pub fn max_compressed_size(element_count: usize, data_type: FpZipType) -> usize {
285 let element_size = match data_type {
286 FpZipType::Float => 4,
287 FpZipType::Double => 8,
288 };
289 let data_size = element_count * element_size;
290 data_size + (data_size / 20) + 128
291}
292
293pub struct FpZipCompressor {
314 nx: u32,
315 ny: u32,
316 nz: u32,
317 nf: u32,
318 prec: u32,
319}
320
321impl FpZipCompressor {
322 pub fn new(nx: u32) -> Self {
324 Self {
325 nx,
326 ny: 1,
327 nz: 1,
328 nf: 1,
329 prec: 0,
330 }
331 }
332
333 pub fn ny(mut self, ny: u32) -> Self {
335 self.ny = ny;
336 self
337 }
338
339 pub fn nz(mut self, nz: u32) -> Self {
341 self.nz = nz;
342 self
343 }
344
345 pub fn nf(mut self, nf: u32) -> Self {
347 self.nf = nf;
348 self
349 }
350
351 pub fn prec(mut self, prec: u32) -> Self {
358 self.prec = prec;
359 self
360 }
361
362 pub fn compress_f32(&self, data: &[f32]) -> Result<Vec<u8>> {
364 compress_f32_prec(data, self.nx, self.ny, self.nz, self.nf, self.prec)
365 }
366
367 pub fn compress_f64(&self, data: &[f64]) -> Result<Vec<u8>> {
369 compress_f64_prec(data, self.nx, self.ny, self.nz, self.nf, self.prec)
370 }
371
372 pub fn compress_f32_into(&self, data: &[f32], dest: &mut [u8]) -> Result<usize> {
374 let compressed = self.compress_f32(data)?;
375 if compressed.len() > dest.len() {
376 return Err(FpZipError::BufferTooSmall {
377 needed: compressed.len(),
378 available: dest.len(),
379 });
380 }
381 dest[..compressed.len()].copy_from_slice(&compressed);
382 Ok(compressed.len())
383 }
384
385 pub fn compress_f64_into(&self, data: &[f64], dest: &mut [u8]) -> Result<usize> {
387 let compressed = self.compress_f64(data)?;
388 if compressed.len() > dest.len() {
389 return Err(FpZipError::BufferTooSmall {
390 needed: compressed.len(),
391 available: dest.len(),
392 });
393 }
394 dest[..compressed.len()].copy_from_slice(&compressed);
395 Ok(compressed.len())
396 }
397}
398
399#[cfg(feature = "std")]
405pub fn compress_f32_to_writer<W: std::io::Write>(
406 data: &[f32],
407 writer: &mut W,
408 nx: u32,
409 ny: u32,
410 nz: u32,
411 nf: u32,
412) -> Result<u64> {
413 let compressed = compress_f32(data, nx, ny, nz, nf)?;
414 writer.write_all(&compressed)?;
415 Ok(compressed.len() as u64)
416}
417
418#[cfg(feature = "std")]
422pub fn compress_f64_to_writer<W: std::io::Write>(
423 data: &[f64],
424 writer: &mut W,
425 nx: u32,
426 ny: u32,
427 nz: u32,
428 nf: u32,
429) -> Result<u64> {
430 let compressed = compress_f64(data, nx, ny, nz, nf)?;
431 writer.write_all(&compressed)?;
432 Ok(compressed.len() as u64)
433}
434
435#[cfg(feature = "std")]
439pub fn decompress_f32_from_reader<R: std::io::Read>(
440 reader: &mut R,
441) -> Result<(FpZipHeader, Vec<f32>)> {
442 let mut data = Vec::new();
443 reader.read_to_end(&mut data)?;
444 decompress_f32_impl(&data)
445}
446
447#[cfg(feature = "std")]
451pub fn decompress_f64_from_reader<R: std::io::Read>(
452 reader: &mut R,
453) -> Result<(FpZipHeader, Vec<f64>)> {
454 let mut data = Vec::new();
455 reader.read_to_end(&mut data)?;
456 decompress_f64_impl(&data)
457}
458
459fn validate_dimensions(data_length: usize, nx: u32, ny: u32, nz: u32, nf: u32) -> Result<()> {
460 let expected = nx as u64 * ny as u64 * nz as u64 * nf as u64;
461 if data_length as u64 != expected {
462 return Err(FpZipError::DimensionMismatch {
463 actual: data_length,
464 expected,
465 nx,
466 ny,
467 nz,
468 nf,
469 });
470 }
471 Ok(())
472}