1use std::{
3 self, fs,
4 io::{self, Read},
5 path::Path,
6};
7
8pub fn head(path: impl AsRef<Path>, limit: usize) -> io::Result<Vec<u8>> {
12 let file_size = fs::metadata(&path)?.len();
13 let file_size: usize = if file_size <= std::usize::MAX as u64 {
14 file_size as usize
15 } else {
16 std::usize::MAX
17 };
18 let (read_buffer_size, read_limit) = if file_size <= limit {
19 (file_size, file_size)
20 } else {
21 (limit, limit)
22 };
23 let mut read_buffer = vec![0; read_buffer_size];
24 fs::File::open(&path)?.read_exact(&mut read_buffer[..read_limit])?;
25 Ok(read_buffer)
26}
27
28pub fn head_to_string(path: impl AsRef<Path>, limit: usize) -> io::Result<String> {
36 Ok(String::from_utf8_lossy(&head(path, limit)?).into_owned())
37}
38
39pub fn head_to_string_with_message(
46 path: impl AsRef<Path>,
47 limit: usize,
48 truncation_message: &str,
49) -> io::Result<String> {
50 let mut read_buffer = head(path, limit + 1)?;
51 if read_buffer.len() > limit {
52 read_buffer[(limit - truncation_message.len())..limit]
53 .copy_from_slice(truncation_message.as_bytes());
54 }
55 read_buffer.truncate(limit);
56 Ok(String::from_utf8_lossy(&read_buffer).into_owned())
57}