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