# APT Parser
>
> Looking for the Typescript Version? [It's been moved here...](https://github.com/cnstr/apt-parser-ts)
`apt-parser` is a library for parsing [APT](https://en.wikipedia.org/wiki/APT_(software)) 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`](https://serde.rs) serialized structs.
### Installation
Make sure you have a modern version of Rust (1.56+) using `rustup`.
Then, add the following to your `Cargo.toml`:
```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](https://wiki.debian.org/DebianRepository/Format#A.22Release.22_files).
If you need to access a field that isn't defined, you can use the `get` method.
Here's a simple example:
```rust
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);
```
```rust
struct Release {
architectures: Vec, // => Architectures
no_support_for_architecture_all: Option, // => No-Support-For-Architecture-All
description: Option, // => Description
origin: Option, // => Origin
label: Option, // => Label
suite: Option, // => Suite
version: Option, // => Version
codename: Option, // => Codename
date: Option, // => Date
valid_until: Option, // => Valid-Until
components: Vec, // => Components
md5sum: Option>, // => MD5Sum
sha1sum: Option>, // => SHA1
sha256sum: Option>, // => SHA256
sha512sum: Option>, // => SHA512
not_automatic: Option, // => NotAutomatic
but_automatic_upgrades: Option, // => ButAutomaticUpgrades
acquire_by_hash: Option, // => Acquire-By-Hash
signed_by: Option, // => Signed-By
packages_require_authorization: Option, // => Packages-Require-Authorization
fn from(data: &str) -> Result; // => 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](https://www.debian.org/doc/debian-policy/ch-controlfields.html).
If you need to access a field that isn't defined, you can use the `get` method.
Here's a simple example:
```rust
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
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);
```
```rust
struct Control {
package: String, // => Package
source: Option, // => Source
version: String, // => Version
section: Option, // => Section
priority: Option, // => Priority
architecture: String, // => Architecture
is_essential: Option, // => Essential
depends: Option>, // => Depends
pre_depends: Option>, // => Pre-Depends
recommends: Option>, // => Recommends
suggests: Option>, // => Suggests
replaces: Option>, // => Replaces
enhances: Option>, // => Enhances
breaks: Option>, // => Breaks
conflicts: Option>, // => Conflicts
installed_size: Option, // => Installed-Size
maintainer: Option, // => Maintainer
description: Option, // => Description
homepage: Option, // => Homepage
built_using: Option, // => Built-Using
package_type: Option, // => Package-Type
tags: Option>, // => Tags
fn from(data: &str) -> Result; // => 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](https://wiki.debian.org/DebianRepository/Format#A.22Packages.22_Indices).
If you need to access a field that isn't defined, you can use the `get` method.
Here's a simple example:
```rust
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);
}
```
```rust
struct Packages {
packages: Vec,
fn from(data: &str) -> Result; // => 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, // => Source
version: String, // => Version
section: Option, // => Section
priority: Option, // => Priority
architecture: String, // => Architecture
is_essential: Option, // => Essential
depends: Option>, // => Depends
pre_depends: Option>, // => Pre-Depends
recommends: Option>, // => Recommends
suggests: Option>, // => Suggests
replaces: Option>, // => Replaces
enhances: Option>, // => Enhances
breaks: Option>, // => Breaks
conflicts: Option>, // => Conflicts
installed_size: Option, // => Installed-Size
maintainer: Option, // => Maintainer
description: Option, // => Description
homepage: Option, // => Homepage
built_using: Option, // => Built-Using
package_type: Option, // => Package-Type
tags: Option>, // => Tags
filename: String, // => Filename
size: i64, // => Size
md5sum: Option, // => MD5sum
sha1sum: Option, // => SHA1
sha256sum: Option, // => SHA256
sha512sum: Option, // => SHA512
description_md5sum: Option, // => Description-md5
fn get(&self, key: &str) -> Option<&str>; // => Retrieve a raw field value
}
```
> Copyright (c) 2023 Aarnav Tale