1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
#[cfg(not(target_arch = "wasm32"))]
use std::path::Path;
use std::path::PathBuf;
use failure::Error;
use reqwest::{
header::{RANGE, USER_AGENT},
Client, Url,
};
#[derive(Debug, Clone)]
pub struct Source(SourceInner);
#[derive(Debug, Clone)]
enum SourceInner {
Local(PathBuf),
Remote {
client: Client,
url: Url,
},
}
impl Source {
pub fn new<T: Into<Self>>(thing: T) -> Self {
thing.into()
}
pub async fn fetch(&self, start: u64, len: u64) -> Result<Vec<u8>, Error> {
match &self.0 {
SourceInner::Local(path) => {
let mut f = File::open(&path)?;
f.seek(SeekFrom::Start(start))?;
let mut buf = vec![0; len as usize];
f.read_exact(&mut buf)?;
Ok(buf)
}
SourceInner::Remote { client, url } => {
let rsp = client
.get(url.clone())
.header(USER_AGENT, "alice-rs")
.header(RANGE, format!("bytes={}-{}", start, start + len - 1))
.send()
.await?
.error_for_status()?;
let bytes = rsp.bytes().await?;
Ok(bytes.as_ref().to_vec())
}
}
}
}
impl From<Url> for Source {
fn from(url: Url) -> Self {
Self(SourceInner::Remote {
client: Client::new(),
url,
})
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<&Path> for Source {
fn from(path: &Path) -> Self {
path.to_path_buf().into()
}
}
#[cfg(not(target_arch = "wasm32"))]
impl From<PathBuf> for Source {
fn from(path_buf: PathBuf) -> Self {
Self(SourceInner::Local(path_buf))
}
}