103 lines
3.1 KiB
Rust
103 lines
3.1 KiB
Rust
use {
|
|
crate::Package,
|
|
hpk_package::ron,
|
|
rayon::prelude::*,
|
|
serde::{Deserialize, Serialize},
|
|
std::{
|
|
collections::HashMap,
|
|
error::Error,
|
|
io::Read,
|
|
sync::{mpsc::Sender, Mutex, PoisonError},
|
|
time::Duration,
|
|
},
|
|
url::Url,
|
|
};
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
/// A struct representing all of the packages available in a remote repository
|
|
pub struct Repository {
|
|
/// The unique name for this repository
|
|
pub name: String,
|
|
/// The base url for this repository
|
|
pub base_url: Url,
|
|
/// a `HashMap` representing all available packages on this server, with the
|
|
/// keys being the unique name of each package
|
|
pub packages: HashMap<String, Package>,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
/// Messages sent to the caller thread when fetching an update for a repository
|
|
pub enum Message {
|
|
ContentLength(usize),
|
|
BytesRead(usize),
|
|
Failure(String),
|
|
Success(usize),
|
|
}
|
|
|
|
impl Repository {
|
|
pub fn build(name: &str, url: &Url, sender: Sender<Message>) -> Result<Self, Box<dyn Error>> {
|
|
let url = url.join("packages.ron.zstd")?;
|
|
let resp = ureq::get(&url.to_string())
|
|
.timeout(Duration::from_secs(10))
|
|
.call()?;
|
|
if let Some(val) = resp.header("Content-Length") {
|
|
if let Ok(num) = val.parse::<usize>() {
|
|
sender.send(Message::ContentLength(num))?;
|
|
}
|
|
}
|
|
let reader = resp.into_reader();
|
|
let mut reader = zstd::Decoder::new(reader)?;
|
|
let mut buf = vec![];
|
|
loop {
|
|
let bytes = reader.read(&mut buf)?;
|
|
if bytes == 0 {
|
|
break;
|
|
}
|
|
sender.send(Message::BytesRead(bytes))?;
|
|
}
|
|
let packages = ron::de::from_bytes(&buf)?;
|
|
Ok(Self {
|
|
name: name.to_string(),
|
|
base_url: url.clone(),
|
|
packages,
|
|
})
|
|
}
|
|
|
|
pub fn search_names(&self, query: &str) -> Result<Vec<&Package>, PoisonError<Vec<&Package>>> {
|
|
let mut results = vec![];
|
|
if let Some(p) = self.packages.get(query) {
|
|
results.push(p);
|
|
}
|
|
let results = Mutex::new(results);
|
|
self.packages.par_iter().for_each(|(k, v)| {
|
|
if k.contains(query) {
|
|
if let Ok(mut r) = results.lock() {
|
|
r.push(v);
|
|
}
|
|
}
|
|
});
|
|
let results = results.into_inner()?;
|
|
Ok(results)
|
|
}
|
|
|
|
pub fn search_all(&self, query: &str) -> Result<Vec<&Package>, PoisonError<Vec<&Package>>> {
|
|
let mut results = vec![];
|
|
if let Some(p) = self.packages.get(query) {
|
|
results.push(p);
|
|
}
|
|
let results = Mutex::new(results);
|
|
self.packages.par_iter().for_each(|(k, v)| {
|
|
if k.contains(query)
|
|
|| v.description.contains(query)
|
|
|| v.long_description.contains(query)
|
|
{
|
|
if let Ok(mut r) = results.lock() {
|
|
r.push(v);
|
|
}
|
|
}
|
|
});
|
|
let results = results.into_inner()?;
|
|
Ok(results)
|
|
}
|
|
}
|