music_player/src/net_reader.rs

76 lines
1.7 KiB
Rust

use std::{
io::{
self,
Read,
Seek,
SeekFrom,
},
};
use anyhow::{
Result,
anyhow,
};
pub struct NetReader {
client: reqwest::blocking::Client,
url: String,
len: u64,
cursor: u64,
}
impl NetReader {
pub fn new (url: String) -> Result <Self> {
let client = reqwest::blocking::Client::new ();
let len = client.head (&url).send ()?.content_length ().ok_or_else (|| anyhow! ("Couldn't get content-length of URL"))?;
Ok (NetReader {
client,
url,
cursor: 0,
len,
})
}
}
impl Read for NetReader {
fn read (&mut self, dest: &mut [u8]) -> io::Result <usize>
{
tracing::trace! ("NetReader reading {}-{}", self.cursor, self.cursor + dest.len () as u64);
let range_hdr = format! ("bytes={}-{}", self.cursor, self.cursor + dest.len () as u64 - 1);
let mut resp = self.client.get (&self.url)
.header (reqwest::header::RANGE, range_hdr)
.send ()
.map_err (|e| io::Error::new (io::ErrorKind::ConnectionRefused, e))?;
let mut cursor = std::io::Cursor::new (dest);
let bytes_moved = resp.copy_to (&mut cursor)
.map_err (|e| io::Error::new (io::ErrorKind::ConnectionReset, e))?;
self.cursor += bytes_moved;
tracing::trace! ("NetReader read {} bytes", bytes_moved);
Ok (bytes_moved.try_into ().unwrap ())
}
}
impl Seek for NetReader {
fn seek (&mut self, pos: SeekFrom) -> io::Result <u64>
{
// If your data is as big as 63 bits you'll just have
// to suffer I guess
let new_cursor = match pos {
SeekFrom::Start (x) => x as i64,
SeekFrom::Current (x) => self.cursor as i64 + x,
SeekFrom::End (x) => self.len as i64 + x,
};
let new_cursor = u64::try_from (new_cursor).map_err (|e| io::Error::new (io::ErrorKind::InvalidInput, e))?;
self.cursor = new_cursor;
Ok (self.cursor)
}
}