1mod traits;
14
15pub use traits::{
16 ByteRange, CogSupport, DataSink, DataSource, OverviewSupport, RasterRead, RasterWrite,
17};
18
19#[cfg(feature = "async")]
20pub use traits::{AsyncDataSource, AsyncRasterRead};
21
22#[cfg(feature = "std")]
23mod file {
24 use std::fs::File;
27 use std::io::{Read, Seek, SeekFrom};
28 use std::path::{Path, PathBuf};
29 use std::sync::Mutex;
30
31 use crate::error::{IoError, OxiGdalError, Result};
32 use crate::io::{ByteRange, DataSource};
33
34 pub struct FileDataSource {
36 path: PathBuf,
37 file: Mutex<File>,
38 size: u64,
39 }
40
41 impl FileDataSource {
42 pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
47 let path = path.as_ref().to_path_buf();
48 let file = File::open(&path).map_err(|e| {
49 OxiGdalError::Io(IoError::Read {
50 message: format!("Failed to open file '{}': {}", path.display(), e),
51 })
52 })?;
53
54 let metadata = file.metadata().map_err(|e| {
55 OxiGdalError::Io(IoError::Read {
56 message: format!("Failed to get file metadata: {e}"),
57 })
58 })?;
59
60 Ok(Self {
61 path,
62 file: Mutex::new(file),
63 size: metadata.len(),
64 })
65 }
66
67 #[must_use]
69 pub fn path(&self) -> &Path {
70 &self.path
71 }
72 }
73
74 impl DataSource for FileDataSource {
75 fn size(&self) -> Result<u64> {
76 Ok(self.size)
77 }
78
79 fn read_range(&self, range: ByteRange) -> Result<Vec<u8>> {
80 let mut file = self.file.lock().map_err(|e| OxiGdalError::Internal {
81 message: format!("Failed to lock file mutex: {e}"),
82 })?;
83
84 file.seek(SeekFrom::Start(range.start)).map_err(|_| {
85 OxiGdalError::Io(IoError::Seek {
86 position: range.start,
87 })
88 })?;
89
90 let len = range.len() as usize;
91 let mut buffer = vec![0u8; len];
92 file.read_exact(&mut buffer).map_err(|e| {
93 OxiGdalError::Io(IoError::Read {
94 message: format!(
95 "Failed to read {} bytes at offset {}: {}",
96 len, range.start, e
97 ),
98 })
99 })?;
100
101 Ok(buffer)
102 }
103 }
104
105 impl std::fmt::Debug for FileDataSource {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("FileDataSource")
108 .field("path", &self.path)
109 .field("size", &self.size)
110 .finish()
111 }
112 }
113}
114
115#[cfg(feature = "std")]
116pub use file::FileDataSource;