llmcc_core/
file.rs

1use std::fs::File as StdFile;
2use std::hash::{DefaultHasher, Hash, Hasher};
3use std::io::Read;
4use std::sync::Arc;
5
6#[derive(Debug, Clone, Default)]
7pub struct FileId {
8    pub path: Option<String>,
9    content: Arc<[u8]>,
10    pub content_hash: u64,
11}
12
13impl FileId {
14    pub fn new_path(path: String) -> std::io::Result<Self> {
15        let mut file = StdFile::open(&path)?;
16        let capacity = file.metadata().map(|meta| meta.len() as usize).unwrap_or(0);
17        let mut content = Vec::with_capacity(capacity);
18        file.read_to_end(&mut content)?;
19
20        let mut hasher = DefaultHasher::new();
21        content.hash(&mut hasher);
22        let content_hash = hasher.finish();
23
24        Ok(FileId {
25            path: Some(path),
26            content: Arc::from(content),
27            content_hash,
28        })
29    }
30
31    pub fn new_content(content: Vec<u8>) -> Self {
32        let mut hasher = DefaultHasher::new();
33        hasher.write(&content);
34        let content_hash = hasher.finish();
35
36        FileId {
37            path: None,
38            content: Arc::from(content),
39            content_hash,
40        }
41    }
42
43    pub fn content(&self) -> &[u8] {
44        self.content.as_ref()
45    }
46
47    pub fn get_text(&self, start_byte: usize, end_byte: usize) -> Option<String> {
48        let content_bytes = self.content();
49
50        if start_byte > end_byte
51            || start_byte > content_bytes.len()
52            || end_byte > content_bytes.len()
53        {
54            return None;
55        }
56
57        let slice = &content_bytes[start_byte..end_byte];
58        Some(String::from_utf8_lossy(slice).into_owned())
59    }
60
61    pub fn get_full_text(&self) -> Option<String> {
62        let content_bytes = self.content();
63        Some(String::from_utf8_lossy(content_bytes).into_owned())
64    }
65}
66
67#[derive(Debug, Clone, Default)]
68pub struct File {
69    // TODO: add cache and all other stuff
70    pub file: FileId,
71}
72
73impl File {
74    pub fn new_source(source: Vec<u8>) -> Self {
75        File {
76            file: FileId::new_content(source),
77        }
78    }
79
80    pub fn new_file(file: String) -> std::io::Result<Self> {
81        Ok(File {
82            file: FileId::new_path(file)?,
83        })
84    }
85
86    pub fn content(&self) -> &[u8] {
87        self.file.content()
88    }
89
90    pub fn get_text(&self, start: usize, end: usize) -> String {
91        self.file.get_text(start, end).unwrap()
92    }
93
94    pub fn opt_get_text(&self, start: usize, end: usize) -> Option<String> {
95        self.file.get_text(start, end)
96    }
97
98    pub fn path(&self) -> Option<&str> {
99        self.file.path.as_deref()
100    }
101}