Skip to main content

git_plumber/tui/widget/pack_obj_details/
config.rs

1use ratatui::style::Color;
2use std::fmt;
3
4// Constants for formatting
5pub const COLORS: [Color; 4] = [Color::Blue, Color::Magenta, Color::Cyan, Color::Red];
6pub const PREVIEW_SIZE_LIMIT: usize = 1000;
7pub const HEX_PREVIEW_LIMIT: usize = 32;
8
9#[derive(Debug, Clone, Copy, PartialEq)]
10pub enum HeaderSection {
11    Size,
12    Hash,
13    Offset,
14}
15
16impl fmt::Display for HeaderSection {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        match self {
19            Self::Size => write!(f, "size"),
20            Self::Hash => write!(f, "hash"),
21            Self::Offset => write!(f, "offset"),
22        }
23    }
24}
25
26impl HeaderSection {
27    pub fn from_byte_position(
28        byte_index: usize,
29        obj_type: crate::git::pack::ObjectType,
30        raw_data_len: usize,
31        size_byte_count: usize,
32    ) -> Self {
33        const HASH_BYTES: usize = 20;
34        let is_ref_delta_hash = obj_type == crate::git::pack::ObjectType::RefDelta
35            && raw_data_len >= HASH_BYTES
36            && byte_index >= raw_data_len - HASH_BYTES;
37
38        let is_ofs_delta_offset =
39            obj_type == crate::git::pack::ObjectType::OfsDelta && byte_index >= size_byte_count;
40
41        if is_ref_delta_hash {
42            Self::Hash
43        } else if is_ofs_delta_offset {
44            Self::Offset
45        } else {
46            Self::Size
47        }
48    }
49}
50
51// Helper function to calculate the number of bytes used for size encoding
52pub fn calculate_size_byte_count(obj_type: crate::git::pack::ObjectType, raw_data: &[u8]) -> usize {
53    const HASH_BYTES: usize = 20;
54    match obj_type {
55        crate::git::pack::ObjectType::RefDelta => {
56            // RefDelta: size bytes + 20-byte hash
57            raw_data.len() - HASH_BYTES
58        }
59        crate::git::pack::ObjectType::OfsDelta => {
60            // OfsDelta: find where size encoding ends
61            let mut size_bytes = 0;
62            for (i, &byte) in raw_data.iter().enumerate() {
63                size_bytes = i + 1;
64                if byte & 0x80 == 0 {
65                    // No continuation bit, this is the last size byte
66                    break;
67                }
68            }
69            size_bytes
70        }
71        _ => raw_data.len(), // Regular objects use all bytes for size
72    }
73}
74
75// Add Adler-32 checksum calculation function
76pub fn calculate_adler32(data: &[u8]) -> u32 {
77    const ADLER32_MODULUS: u32 = 65521;
78    let mut a: u32 = 1;
79    let mut b: u32 = 0;
80
81    for &byte in data {
82        a = (a + u32::from(byte)) % ADLER32_MODULUS;
83        b = (b + a) % ADLER32_MODULUS;
84    }
85
86    (b << 16) | a
87}