Last active
April 21, 2024 08:17
-
-
Save sheepla/598f33b86518c7fab17917c801ea3ef8 to your computer and use it in GitHub Desktop.
Search Arch Linux pacakges via official Web interface in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "pacsearch-rs" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
derive_builder = "0.20.0" | |
reqwest = { version = "0.12.4", features = ["json"] } | |
serde = "1.0.198" | |
serde_derive = "1.0.198" | |
serde_json = "1.0.116" | |
tokio = { version = "1.37.0", features = ["full"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Compiling pacsearch-rs v0.1.0 (/home/sheepla/ghq/github.com/sheepla/pacsearch-rs) | |
Finished test [unoptimized + debuginfo] target(s) in 1.65s | |
Running unittests src/lib.rs (target/debug/deps/pacsearch_rs-cf600b48346390d6) | |
running 2 tests | |
PackageSearchParamBuilder: Ok(PackageSearchParam { query: Some("query"), name: Some("name"), description: None, repo: Some(Core), arch: Some(Any), maintainer: None, packager: None, flagged: Some(NotFlagged) }) | |
test types::test_package_search_param_builder ... ok | |
param: PackageSearchParam { query: Some("pacman"), name: None, description: None, repo: Some(Core), arch: None, maintainer: None, packager: None, flagged: None } | |
------------ | |
core/pacman v6.1.0 - A library-based package manager with dependency support | |
core/pacman-mirrorlist v20231001 - Arch Linux mirror list for use by pacman | |
------------ | |
test test_search_packages ... ok | |
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.97s | |
Doc-tests pacsearch-rs | |
running 0 tests | |
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mod types; | |
use crate::types::*; | |
use reqwest; | |
use std::collections::HashMap; | |
pub async fn search_packages( | |
param: PackageSearchParam, | |
) -> Result<PackageSearchResult, reqwest::Error> { | |
let client = reqwest::Client::new(); | |
let response = client | |
.get("https://archlinux.org/packages/search/json/") | |
.query(&build_query_param(param)) | |
.send() | |
.await?; | |
let search_result: PackageSearchResult = response.json().await?; | |
Ok(search_result) | |
} | |
fn build_query_param(param: PackageSearchParam) -> HashMap<String, String> { | |
let mut q = HashMap::new(); | |
if let Some(query) = param.query { | |
q.insert("q".to_string(), query); | |
} | |
if let Some(name) = param.name { | |
q.insert("name".to_string(), name); | |
} | |
if let Some(description) = param.description { | |
q.insert("description".to_string(), description); | |
} | |
if let Some(repo) = param.repo { | |
q.insert("repo".to_string(), repo.to_query_param_value().to_string()); | |
} | |
if let Some(arch) = param.arch { | |
q.insert("arch".to_string(), arch.to_query_param_value().to_string()); | |
} | |
if let Some(maintainer) = param.maintainer { | |
q.insert("maintainer".to_string(), maintainer); | |
} | |
if let Some(packager) = param.packager { | |
q.insert("packager".to_string(), packager); | |
} | |
if let Some(flagged) = param.flagged { | |
q.insert("flagged".to_string(), flagged.to_query_param_value().to_string()); | |
} | |
q | |
} | |
#[tokio::test] | |
async fn test_search_packages() { | |
let param = PackageSearchParamBuilder::default() | |
.query("pacman") | |
.repo(Repo::Core) | |
.build() | |
.unwrap(); | |
println!("param: {:?}", param); | |
let packages = search_packages(param).await.unwrap(); | |
println!("------------"); | |
for pkg in &packages.results { | |
println!("{}/{} v{} - {}", pkg.repo, pkg.pkgname, pkg.pkgver, pkg.pkgdesc); | |
} | |
println!("------------"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use derive_builder::Builder; | |
use serde_derive::{Deserialize, Serialize}; | |
use serde_json::Value; | |
#[derive(Builder, Default, Debug)] | |
#[builder(default, public, setter(into, strip_option))] | |
pub struct PackageSearchParam { | |
pub query: Option<String>, | |
pub name: Option<String>, | |
pub description: Option<String>, | |
pub repo: Option<Repo>, | |
pub arch: Option<Arch>, | |
pub maintainer: Option<String>, | |
pub packager: Option<String>, | |
pub flagged: Option<IsFlagged>, | |
} | |
#[test] | |
fn test_package_search_param_builder() { | |
let b = PackageSearchParamBuilder::default() | |
.query("query") | |
.name("name") | |
.repo(Repo::Core) | |
.arch(Arch::Any) | |
.flagged(IsFlagged::NotFlagged) | |
.build(); | |
println!("PackageSearchParamBuilder: {:?}", b); | |
b.unwrap(); | |
} | |
#[derive(Clone, Debug)] | |
pub enum Repo { | |
Core, | |
CoreTesting, | |
Extra, | |
ExtraTesting, | |
Multilib, | |
MultilibTesting, | |
} | |
impl Repo { | |
pub fn to_query_param_value(&self) -> &str { | |
match self { | |
Self::Core => "Core", | |
Self::CoreTesting => "Core-Testing", | |
Self::Extra => "Extra", | |
Self::ExtraTesting => "Extra-Testing", | |
Self::Multilib => "Multilib", | |
Self::MultilibTesting => "Multilib-Testing", | |
} | |
} | |
} | |
#[derive(Clone, Debug)] | |
pub enum Arch { | |
Any, | |
X86_64, | |
} | |
impl Arch { | |
pub fn to_query_param_value(&self) -> &str { | |
match self { | |
Self::Any => "any", | |
Self::X86_64 => "X86_64", | |
} | |
} | |
} | |
#[derive(Clone, Debug)] | |
pub enum IsFlagged { | |
Flagged, | |
NotFlagged, | |
} | |
impl IsFlagged { | |
pub fn to_query_param_value(&self) -> &str { | |
match self { | |
Self::Flagged => "Flagged", | |
Self::NotFlagged => "Not+Flagged", | |
} | |
} | |
} | |
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] | |
pub struct PackageSearchResult { | |
pub version: i64, | |
pub limit: i64, | |
pub valid: bool, | |
pub results: Vec<Package>, | |
pub num_pages: i64, | |
pub page: i64, | |
} | |
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] | |
#[serde(rename = "result")] | |
pub struct Package { | |
pub pkgname: String, | |
pub pkgbase: String, | |
pub repo: String, | |
pub arch: String, | |
pub pkgver: String, | |
pub pkgrel: String, | |
pub epoch: i64, | |
pub pkgdesc: String, | |
pub url: String, | |
pub filename: String, | |
pub compressed_size: i64, | |
pub installed_size: i64, | |
pub build_date: String, | |
pub last_update: String, | |
pub flag_date: Option<String>, | |
pub maintainers: Vec<String>, | |
pub packager: String, | |
pub groups: Vec<String>, | |
pub licenses: Vec<String>, | |
pub conflicts: Vec<String>, | |
pub provides: Vec<String>, | |
pub replaces: Vec<Value>, | |
pub depends: Vec<String>, | |
pub optdepends: Vec<String>, | |
pub makedepends: Vec<String>, | |
pub checkdepends: Vec<String>, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment