7 stable releases
1.0.6 | Apr 24, 2023 |
---|---|
1.0.3 | Apr 23, 2023 |
1.0.2 | Apr 19, 2023 |
1.0.0 | Feb 12, 2023 |
#861 in Parser implementations
32 downloads per month
Used in 2 crates
42KB
1K
SLoC
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]
# You can also use the latest version
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>, // => Architectures
no_support_for_architecture_all: Option<bool>, // => No-Support-For-Architecture-All
description: Option<String>, // => Description
origin: Option<String>, // => Origin
label: Option<String>, // => Label
suite: Option<String>, // => Suite
version: Option<String>, // => Version
codename: Option<String>, // => Codename
date: Option<String>, // => Date
valid_until: Option<String>, // => Valid-Until
components: Vec<String>, // => Components
md5sum: Option<Vec<ReleaseHash>>, // => MD5Sum
sha1sum: Option<Vec<ReleaseHash>>, // => SHA1
sha256sum: Option<Vec<ReleaseHash>>, // => SHA256
sha512sum: Option<Vec<ReleaseHash>>, // => SHA512
not_automatic: Option<bool>, // => NotAutomatic
but_automatic_upgrades: Option<bool>, // => ButAutomaticUpgrades
acquire_by_hash: Option<bool>, // => Acquire-By-Hash
signed_by: Option<String>, // => Signed-By
packages_require_authorization: Option<bool>, // => Packages-Require-Authorization
fn from(data: &str) -> Result<Self, APTError>; // => Parse a Release file
fn get(&self, key: &str) -> Option<&str>; // => Retrieve a raw field value
}
// A struct for holding the hash information for a Release file
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, // => Package
source: Option<String>, // => Source
version: String, // => Version
section: Option<String>, // => Section
priority: Option<String>, // => Priority
architecture: String, // => Architecture
is_essential: Option<bool>, // => Essential
depends: Option<Vec<String>>, // => Depends
pre_depends: Option<Vec<String>>, // => Pre-Depends
recommends: Option<Vec<String>>, // => Recommends
suggests: Option<Vec<String>>, // => Suggests
replaces: Option<Vec<String>>, // => Replaces
enhances: Option<Vec<String>>, // => Enhances
breaks: Option<Vec<String>>, // => Breaks
conflicts: Option<Vec<String>>, // => Conflicts
installed_size: Option<i64>, // => Installed-Size
maintainer: Option<String>, // => Maintainer
description: Option<String>, // => Description
homepage: Option<String>, // => Homepage
built_using: Option<String>, // => Built-Using
package_type: Option<String>, // => Package-Type
tags: Option<Vec<String>>, // => Tags
fn from(data: &str) -> Result<Self, APTError>; // => Parse a Control file
fn get(&self, key: &str) -> Option<&str>; // => Retrieve a raw field value
}
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>; // => Parse a Packages file
fn len(&self) -> usize; // => Get the number of packages
}
impl Iterator for Packages;
impl Index for Packages;
struct Package {
package: String, // => Package
source: Option<String>, // => Source
version: String, // => Version
section: Option<String>, // => Section
priority: Option<String>, // => Priority
architecture: String, // => Architecture
is_essential: Option<bool>, // => Essential
depends: Option<Vec<String>>, // => Depends
pre_depends: Option<Vec<String>>, // => Pre-Depends
recommends: Option<Vec<String>>, // => Recommends
suggests: Option<Vec<String>>, // => Suggests
replaces: Option<Vec<String>>, // => Replaces
enhances: Option<Vec<String>>, // => Enhances
breaks: Option<Vec<String>>, // => Breaks
conflicts: Option<Vec<String>>, // => Conflicts
installed_size: Option<i64>, // => Installed-Size
maintainer: Option<String>, // => Maintainer
description: Option<String>, // => Description
homepage: Option<String>, // => Homepage
built_using: Option<String>, // => Built-Using
package_type: Option<String>, // => Package-Type
tags: Option<Vec<String>>, // => Tags
filename: String, // => Filename
size: i64, // => Size
md5sum: Option<String>, // => MD5sum
sha1sum: Option<String>, // => SHA1
sha256sum: Option<String>, // => SHA256
sha512sum: Option<String>, // => SHA512
description_md5sum: Option<String>, // => Description-md5
fn get(&self, key: &str) -> Option<&str>; // => Retrieve a raw field value
}
Copyright (c) 2023 Aarnav Tale
Dependencies
~3–4.5MB
~79K SLoC