APT Parser
Looking for the Typescript Version? It's been moved here...
apt-parser is a library for parsing APT list files.
An APT repository normally consists of a Release file, Packages file, and compressed binary packages.
The library is able to parse these files and return them as serde serialized structs.
Installation
Make sure you have a modern version of Rust (1.56+) using rustup.
Then, add the following to your Cargo.toml:
[dependencies]
apt-parser = "1.0.0"
Release Parsing
Release files are the main entry point for an APT repository.
The Release struct has strict types for all documented fields in the Release file.
If you need to access a field that isn't defined, you can use the get method.
Here's a simple example:
use apt_parser::Release;
use surf::get;
let data = get("http://archive.ubuntu.com/ubuntu/dists/jammy/Release")
.await?
.body_string()
.await?;
let release = match Release::from(data) {
Ok(release) => release,
Err(err) => panic!("Failed to parse Release file: {}", err),
}
assert_eq!(release.origin, "Ubuntu");
assert_eq!(release.version, "22.04");
assert_eq!(release.get("InvalidKey"), None);
struct Release {
architectures: Vec<String>, no_support_for_architecture_all: Option<bool>, description: Option<String>, origin: Option<String>, label: Option<String>, suite: Option<String>, version: Option<String>, codename: Option<String>, date: Option<String>, valid_until: Option<String>, components: Vec<String>, md5sum: Option<Vec<ReleaseHash>>, sha1sum: Option<Vec<ReleaseHash>>, sha256sum: Option<Vec<ReleaseHash>>, sha512sum: Option<Vec<ReleaseHash>>, not_automatic: Option<bool>, but_automatic_upgrades: Option<bool>, acquire_by_hash: Option<bool>, signed_by: Option<String>, packages_require_authorization: Option<bool>,
fn from(data: &str) -> Result<Self, APTError>; fn get(&self, key: &str) -> Option<&str>; }
struct ReleaseHash {
filename: String,
hash: String,
size: u64,
}
Control File Parsing
Control files are used to describe the contents of a binary package.
The Control struct has strict types for all documented fields in the control file.
If you need to access a field that isn't defined, you can use the get method.
Here's a simple example:
use apt_parser::Control;
let data = "
Package: com.amywhile.signalreborn
Architecture: iphoneos-arm
Description: Visualise your nearby cell towers
Depends: firmware (>= 12.2) | org.swift.libswift
Maintainer: Amy While <support@anamy.gay>
Section: Applications
Version: 2.2.1-2
Installed-Size: 1536
Custom-Key: cool-value
";
let control = match Control::from(data) {
Ok(control) => control,
Err(err) => panic!("Failed to parse Control file: {}", err),
}
assert_eq!(control.version, "2.2.1-2");
assert_eq!(control.package, "com.amywhile.signalreborn");
assert_eq!(control.get("Custom-Key"), Some("cool-value"));
assert_eq!(control.get("Invalid-Key"), None);
struct Control {
package: String, source: Option<String>, version: String, section: Option<String>, priority: Option<String>, architecture: String, is_essential: Option<bool>, depends: Option<Vec<String>>, pre_depends: Option<Vec<String>>, recommends: Option<Vec<String>>, suggests: Option<Vec<String>>, replaces: Option<Vec<String>>, enhances: Option<Vec<String>>, breaks: Option<Vec<String>>, conflicts: Option<Vec<String>>, installed_size: Option<i64>, maintainer: Option<String>, description: Option<String>, homepage: Option<String>, built_using: Option<String>, package_type: Option<String>, tags: Option<Vec<String>>,
fn from(data: &str) -> Result<Self, APTError>; fn get(&self, key: &str) -> Option<&str>; }
Packages Parsing
Packages files are used to describe the contents of a repository.
The Packages struct implements an iterator and has methods for accessing the packages.
The Package struct has strict types for all documented fields in the Packages file.
If you need to access a field that isn't defined, you can use the get method.
Here's a simple example:
use apt_parser::Packages;
use surf::get;
let data = get("https://repo.chariz.com/Packages")
.await?
.body_string()
.await?;
let packages = match Packages::from(&data) {
Ok(packages) => packages,
Err(err) => panic!("Failed to parse Packages file: {}", err),
}
assert_eq!(packages.len(), 419);
for package in packages {
println!("{}: {}", package.package, package.version);
}
struct Packages {
packages: Vec<Package>,
fn from(data: &str) -> Result<Self, APTError>; fn len(&self) -> usize; }
impl Iterator for Packages;
impl Index for Packages;
struct Package {
package: String, source: Option<String>, version: String, section: Option<String>, priority: Option<String>, architecture: String, is_essential: Option<bool>, depends: Option<Vec<String>>, pre_depends: Option<Vec<String>>, recommends: Option<Vec<String>>, suggests: Option<Vec<String>>, replaces: Option<Vec<String>>, enhances: Option<Vec<String>>, breaks: Option<Vec<String>>, conflicts: Option<Vec<String>>, installed_size: Option<i64>, maintainer: Option<String>, description: Option<String>, homepage: Option<String>, built_using: Option<String>, package_type: Option<String>, tags: Option<Vec<String>>, filename: String, size: i64, md5sum: Option<String>, sha1sum: Option<String>, sha256sum: Option<String>, sha512sum: Option<String>, description_md5sum: Option<String>,
fn get(&self, key: &str) -> Option<&str>; }
Copyright (c) 2023 Aarnav Tale