summaryrefslogtreecommitdiff
path: root/src/chunker/rw/storage.rs
blob: 13452d075a14ab8645bfeca866e3e13e70270070 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
pub mod build;
pub mod write;

pub use build::build;
pub use write::write;

use std::path::{Path, PathBuf};

/// Information about a chunk for index file
#[derive(Debug, Clone)]
pub struct ChunkInfo {
    /// Index of the chunk in the file
    pub index: usize,
    /// Hash of the chunk (hex string)
    pub hash: String,
    /// Size of the chunk in bytes
    pub size: usize,
    /// Start position in the original file
    pub start: usize,
    /// End position in the original file (exclusive)
    pub end: usize,
}

/// 根据hash值计算chunk文件的存储路径
///
/// # 参数
/// - `storage_dir`: 存储目录
/// - `hash_hex`: chunk的hash值(16进制字符串)
///
/// # 返回
/// 返回chunk文件的完整路径
pub fn get_chunk_path(storage_dir: &Path, hash_hex: &str) -> PathBuf {
    let first_slice = &hash_hex[0..2];
    let second_slice = &hash_hex[2..4];
    storage_dir
        .join(first_slice)
        .join(second_slice)
        .join(hash_hex)
}

/// 根据hash字节数组计算chunk文件的存储路径
///
/// # 参数
/// - `storage_dir`: 存储目录
/// - `hash_bytes`: chunk的hash值(字节数组)
///
/// # 返回
/// 返回chunk文件的完整路径
pub fn get_chunk_path_from_bytes(storage_dir: &Path, hash_bytes: &[u8; 32]) -> PathBuf {
    let hash_hex = hex::encode(hash_bytes);
    get_chunk_path(storage_dir, &hash_hex)
}

/// 生成唯一的文件路径,如果文件已存在则添加数字后缀
///
/// # 参数
/// - `output_dir`: 输出目录
/// - `desired_filename`: 期望的文件名
///
/// # 返回
/// 返回唯一的文件路径
pub fn generate_unique_path(output_dir: &Path, desired_filename: &str) -> PathBuf {
    let desired_path = output_dir.join(desired_filename);
    let mut candidate = desired_path.clone();

    let mut counter = 1;
    while candidate.exists() {
        let path_buf = PathBuf::from(desired_filename);
        if let Some(stem) = path_buf.file_stem() {
            if let Some(ext) = path_buf.extension() {
                let ext_str = ext.to_string_lossy();
                let new_name = if ext_str.is_empty() {
                    format!("{}_{}", stem.to_string_lossy(), counter)
                } else {
                    format!("{}.{}_{}", stem.to_string_lossy(), ext_str, counter)
                };
                candidate = output_dir.join(new_name);
            } else {
                candidate = output_dir.join(format!("{}_{}", stem.to_string_lossy(), counter));
            }
        } else {
            candidate = output_dir.join(format!("{}_{}", desired_filename, counter));
        }
        counter += 1;
    }

    candidate
}