conspire/io/vtk/write/
mod.rs1use crate::io::deflate::zlib_encode;
2use std::path::Path;
3
4const COMPRESSION_BLOCK_SIZE: usize = 32768;
5
6pub enum Compression<P>
7where
8 P: AsRef<Path>,
9{
10 On(P),
11 Off(P),
12}
13
14impl<P> AsRef<Path> for Compression<P>
15where
16 P: AsRef<Path>,
17{
18 fn as_ref(&self) -> &Path {
19 match self {
20 Compression::On(path) => path.as_ref(),
21 Compression::Off(path) => path.as_ref(),
22 }
23 }
24}
25
26pub fn data_array(data: &[u8]) -> String {
27 let mut buffer = Vec::with_capacity(8 + data.len());
28 buffer.extend_from_slice(&(data.len() as u64).to_le_bytes());
29 buffer.extend_from_slice(data);
30 base64(&buffer)
31}
32
33pub fn data_array_compressed(data: &[u8]) -> String {
34 let compressed_blocks: Vec<Vec<u8>> = data
35 .chunks(COMPRESSION_BLOCK_SIZE)
36 .map(zlib_encode)
37 .collect();
38 let num_blocks = compressed_blocks.len() as u64;
39 let last_block_size =
40 data.len() as u64 - num_blocks.saturating_sub(1) * COMPRESSION_BLOCK_SIZE as u64;
41 let mut header = Vec::with_capacity(24 + compressed_blocks.len() * 8);
42 header.extend_from_slice(&num_blocks.to_le_bytes());
43 header.extend_from_slice(&(COMPRESSION_BLOCK_SIZE as u64).to_le_bytes());
44 header.extend_from_slice(&last_block_size.to_le_bytes());
45 for block in &compressed_blocks {
46 header.extend_from_slice(&(block.len() as u64).to_le_bytes());
47 }
48 let mut payload = Vec::with_capacity(compressed_blocks.iter().map(Vec::len).sum::<usize>());
49 for block in &compressed_blocks {
50 payload.extend_from_slice(block);
51 }
52 base64(&header) + &base64(&payload)
53}
54
55pub fn base64(bytes: &[u8]) -> String {
56 const ALPHABET: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57 let mut out = String::with_capacity(bytes.len().div_ceil(3) * 4);
58 for chunk in bytes.chunks(3) {
59 let triple = ((chunk[0] as u32) << 16)
60 | ((*chunk.get(1).unwrap_or(&0) as u32) << 8)
61 | (*chunk.get(2).unwrap_or(&0) as u32);
62 out.push(ALPHABET[(triple >> 18 & 63) as usize] as char);
63 out.push(ALPHABET[(triple >> 12 & 63) as usize] as char);
64 out.push(if chunk.len() > 1 {
65 ALPHABET[(triple >> 6 & 63) as usize] as char
66 } else {
67 '='
68 });
69 out.push(if chunk.len() > 2 {
70 ALPHABET[(triple & 63) as usize] as char
71 } else {
72 '='
73 });
74 }
75 out
76}