get_file_size/
get_file_size.rs1crate::ix!();
3
4#[async_trait]
5pub trait GetFileSize {
6
7 async fn file_size(&self) -> Result<u64, FileError>;
8}
9
10#[async_trait]
11impl<T> GetFileSize for T
12where
13 T: AsRef<Path> + Send + Sync,
14{
15 async fn file_size(&self) -> Result<u64, FileError> {
16 Ok(tokio::fs::metadata(self.as_ref())
17 .await
18 .map_err(|e| FileError::GetMetadataError { io: e.into() })?
19 .len())
20 }
21}
22
23#[cfg(test)]
24mod test_get_file_size {
25 use super::*;
26 use std::io::Write as IoWrite;
27 use std::path::PathBuf;
28 use tempfile::{tempdir, NamedTempFile};
29 use tokio::fs::create_dir;
30 use tokio::io::AsyncWriteExt;
31
32 #[tokio::test]
34 async fn test_file_size_empty_file_returns_0() {
35 let temp_file = NamedTempFile::new().expect("Failed to create temp file");
36 let file_path = temp_file.path().to_path_buf();
37
38 let size = file_path.file_size().await;
39 assert!(size.is_ok(), "Expected Ok for empty file metadata");
40 assert_eq!(size.unwrap(), 0, "Empty file should have size 0");
41 }
42
43 #[tokio::test]
45 async fn test_file_size_existing_file_with_content() {
46 let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
47 let file_path = temp_file.path().to_path_buf();
48
49 let content = b"Hello, world!";
51 temp_file
52 .write_all(content)
53 .expect("Failed to write content to temp file");
54
55 let size = file_path.file_size().await;
56 assert!(size.is_ok(), "Expected Ok for file with content");
57 assert_eq!(
58 size.unwrap() as usize,
59 content.len(),
60 "File size should match number of bytes written"
61 );
62 }
63
64 #[tokio::test]
66 async fn test_file_size_non_existent_file_returns_error() {
67 let non_existent_path = PathBuf::from("this_file_does_not_exist.xyz");
68 let result = non_existent_path.file_size().await;
69 assert!(result.is_err(), "Expected an error for non-existent file");
70 match result {
71 Err(FileError::GetMetadataError { .. }) => {
72 }
74 _ => panic!("Expected FileError::GetMetadataError for non-existent file"),
75 }
76 }
77
78 #[tokio::test]
81 async fn test_file_size_directory() {
82 let temp_dir = tempdir().expect("Failed to create temp directory");
83 let dir_path = temp_dir.path().to_path_buf();
84
85 let size = dir_path.file_size().await;
86 assert!(size.is_ok(), "Getting metadata for a directory should succeed on most platforms");
89 let size_val = size.unwrap();
90 assert!(
91 size_val >= 0,
92 "Directory size ({} bytes) should be non-negative",
93 size_val
94 );
95 }
96
97 #[tokio::test]
100 async fn test_file_size_nested_directory() {
101 let temp_dir = tempdir().expect("Failed to create temp directory");
102 let nested_dir = temp_dir.path().join("nested");
103 create_dir(&nested_dir).await.expect("Failed to create nested dir");
104
105 let size = nested_dir.file_size().await;
106 assert!(size.is_ok(), "Getting metadata for nested directory should succeed");
107 }
108
109 #[tokio::test]
112 async fn test_file_size_large_file() {
113 let mut temp_file = NamedTempFile::new().expect("Failed to create temp file");
114 let file_path = temp_file.path().to_path_buf();
115
116 let data_size = 1_000_000usize;
118 let data = vec![0u8; data_size];
119 temp_file
120 .write_all(&data)
121 .expect("Failed to write large data to temp file");
122
123 let size = file_path.file_size().await;
124 assert!(size.is_ok(), "Expected Ok for large file metadata");
125 assert_eq!(
126 size.unwrap() as usize,
127 data_size,
128 "File size should match 1 MB of data"
129 );
130 }
131}