MCPcopy Create free account
hub / github.com/Kudaes/MFTool / process_units

Function process_units

parser/src/lib.rs:2776–2868  ·  view source on GitHub ↗

For my future self: The file content is divided into compression units, which comprise as many clusters as indicated by clusters_per_unit. The idea is to iterate over the list of VCNs in the stream content, grouping them by compression unit. If a compression unit begins with a sparse VCN, it is assumed that it is not compressed. If it begins with a real VCN, then it may be compressed,

(vcn_list: &[VCN], cluster_size: usize, clusters_per_unit: usize, file_size: u64, stream_marked_compressed: bool)

Source from the content-addressed store, hash-verified

2774 by simply joining the content of the VCNs that compose it (here the sparse ones are taken into account).
2775*/
2776fn process_units(vcn_list: &[VCN], cluster_size: usize, clusters_per_unit: usize, file_size: u64, stream_marked_compressed: bool) -> Option<Vec<u8>>
2777{
2778 if clusters_per_unit <= 0 { // Can this even happen?
2779 return None;
2780 }
2781
2782 let bytes_per_unit = clusters_per_unit * cluster_size;
2783 let total_clusters_needed = ((file_size + (cluster_size as u64) - 1) / (cluster_size as u64)) as usize; // round up
2784
2785 if vcn_list.len() < total_clusters_needed {
2786 return None;
2787 }
2788
2789 let mut final_output = Vec::with_capacity(file_size as usize);
2790 let mut unit_index = 0usize;
2791 let mut bytes_remaining = file_size as usize;
2792
2793 while bytes_remaining > 0 {
2794 let start = unit_index * clusters_per_unit;
2795 let end = (start + clusters_per_unit).min(vcn_list.len());
2796 let unit_vcns = &vcn_list[start..end];
2797
2798 let logical_len = bytes_remaining.min(bytes_per_unit);
2799
2800 let starts_sparse = unit_vcns.first().map(|v| v.is_sparse).unwrap_or(true);
2801 let first_sparse = unit_vcns.iter().position(|v| v.is_sparse);
2802
2803 // I don't know whether I should keep this check or not
2804 //let only_tail_sparse = has_sparse && !starts_sparse && !has_sparse_middle;
2805
2806 // Unit candidate to LZNT1 decompression
2807 let mut produced: Option<Vec<u8>> = None;
2808 if stream_marked_compressed && !starts_sparse {
2809 let run_end = first_sparse.unwrap_or(unit_vcns.len());
2810 // Adjacent real vcns
2811 let mut stored_prefix = Vec::new();
2812 for i in 0..run_end {
2813 let v = &unit_vcns[i];
2814 let off = i * cluster_size;
2815 if off >= logical_len {
2816 break;
2817 }
2818
2819 // In case we don't have to take the whole content of the last VCN
2820 // because it would exceed the file size
2821 let take = (logical_len - off).min(v.content.len());
2822 stored_prefix.extend_from_slice(&v.content[..take]);
2823 }
2824
2825 if !stored_prefix.is_empty() {
2826 match unsafe { decompress_lznt1_unit(&stored_prefix, bytes_per_unit) } {
2827 Ok(mut dec) => {
2828 if dec.len() > logical_len {
2829 dec.truncate(logical_len);
2830 } else if dec.len() < logical_len {
2831 dec.resize(logical_len, 0); // Fill with zeros at the end if needed
2832 }
2833

Callers 1

get_file_contentFunction · 0.85

Calls 1

decompress_lznt1_unitFunction · 0.85

Tested by

no test coverage detected