1use crate::error::Result;
4use std::io::{Read, Seek, SeekFrom};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub struct ReadInterval {
9 pub start: u64,
10 pub end: u64,
11}
12
13#[derive(Debug, Clone)]
15pub struct LocalFileMedia {
16 path: String,
17 name: String,
18 length: u64,
19}
20
21impl LocalFileMedia {
22 pub fn new(path: &str) -> std::io::Result<Self> {
23 let metadata = std::fs::metadata(path)?;
24 let name = std::path::Path::new(path)
25 .file_name()
26 .and_then(|n| n.to_str())
27 .unwrap_or("unknown")
28 .to_string();
29
30 Ok(Self {
31 path: path.to_string(),
32 name,
33 length: metadata.len(),
34 })
35 }
36
37 pub fn length(&self) -> u64 {
38 self.length
39 }
40
41 pub fn name(&self) -> &str {
42 &self.name
43 }
44
45 pub fn read_range_sync(&self, interval: ReadInterval) -> Result<Vec<u8>> {
47 let mut file = std::fs::File::open(&self.path)?;
48 file.seek(SeekFrom::Start(interval.start))?;
49 let len = (interval.end - interval.start + 1) as usize;
50 let mut buffer = vec![0u8; len];
51 file.read_exact(&mut buffer)?;
52 Ok(buffer)
53 }
54}
55
56#[cfg(feature = "async")]
58use std::future::Future;
59#[cfg(feature = "async")]
60use std::pin::Pin;
61
62#[cfg(feature = "async")]
67#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
68pub trait FileMedia: Send + Sync {
69 fn length(&self) -> u64;
70 fn name(&self) -> &str;
71 fn read_range(
72 &self,
73 interval: ReadInterval,
74 ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send + '_>>;
75}
76
77#[cfg(feature = "async")]
78impl FileMedia for LocalFileMedia {
79 fn length(&self) -> u64 {
80 self.length
81 }
82
83 fn name(&self) -> &str {
84 &self.name
85 }
86
87 fn read_range(
88 &self,
89 interval: ReadInterval,
90 ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + Send + '_>> {
91 let path = self.path.clone();
92 Box::pin(async move {
93 use tokio::io::{AsyncReadExt, AsyncSeekExt};
94 let mut file = tokio::fs::File::open(&path).await?;
95 file.seek(std::io::SeekFrom::Start(interval.start)).await?;
96 let len = (interval.end - interval.start + 1) as usize;
97 let mut buffer = vec![0u8; len];
98 file.read_exact(&mut buffer).await?;
99 Ok(buffer)
100 })
101 }
102}