g3fc

Crates.iog3fc
lib.rsg3fc
version1.1.5
created_at2025-08-05 23:01:17.933284+00
updated_at2025-08-05 23:18:19.808033+00
descriptionA Rust implementation of the G3FC (G3 File Container) format.
homepagehttps://g3pix.com.br/g3fc/
repositoryhttps://github.com/guimaraeslucas/g3fc/tree/main/rust
max_upload_size
id1783159
size97,886
Lucas GuimarĂ£es (guimaraeslucas)

documentation

README

G3FC Archiver - Rust Implementation

The Rust implementation of G3FC is built for performance, memory safety, and concurrency. It leverages Rust's strong type system and modern ecosystem to provide a fast and reliable tool. The code is organized into modules for a clean separation of concerns, and its public API is designed to be integrated into other Rust applications.

This guide focuses on how to use the core logic as a library crate. For setup and dependency information, please see the [[Getting Started (Installation & Dependencies)]] page.


1. Prerequisites

  • Rust: Version 2024 or later.
  • Packages: The script relies on the following packages. You can install them using cargo.
    • anyhow
    • byteorder
    • chrono
    • walkdir
    • clap
    • serde
    • serde_cbor
    • serde_bytes
    • crc32fast
    • uuid
    • zstd
    • aes-gcm
    • pbkdf2
    • sha2
    • rand
    • reed-solomon-erasure

Core Components

The crate's logic is organized into several modules:

  • writer: Contains all logic for creating .g3fc archives, centered around the create_archive function.
  • reader: Provides functions for reading and extracting data from archives, such as read_archive_metadata.
  • commands: Implements the higher-level logic used by the CLI. The functions in this module are excellent examples of how to compose the reader and writer APIs to perform complete operations.
  • helpers: A utility module containing core functions for encryption (encrypt_aes_gcm), key derivation, checksums, and other low-level tasks.
  • Data Structures: The MainHeader, Footer, and FileEntry structs directly map to the binary format. The various ...Args structs (e.g., CreateArgs, ExtractArgs) are used to pass configuration to the public functions.

API Usage & Examples

To use this crate in your own project, add g3fc_rust as a dependency in your Cargo.toml and then use the necessary functions and structs from the modules. The API heavily uses the Result<T, E> type for robust error handling.

Creating an Archive

To create an archive, you construct a CreateArgs struct with your desired configuration and pass it to the writer::create_archive function.

  • Function: writer::create_archive(args: &CreateArgs) -> anyhow::Result<()>
  • Description: Takes a configuration struct and executes the full archive creation workflow.
  • Parameters:
    • args: A reference to a CreateArgs struct, which holds all configuration options like input paths, output path, password, and compression settings.

Example:

use g3fc_rust::writer;
use g3fc_rust::{CreateArgs}; // The struct is in the root, re-exported
use std::path::PathBuf;

fn create_my_archive() -> anyhow::Result<()> {
    // 1. Configure the archive creation options by building the args struct.
    let args = CreateArgs {
        input_paths: vec![PathBuf::from("./my_documents"), PathBuf::from("./archive_this.zip")],
        output: PathBuf::from("./my_archive.g3fc"),
        password: Some("a-strong-password".to_string()),
        compression_level: 12,
        global_compression: false,
        fec_level: 10, // 10% FEC
        split: Some("500MB".to_string()),
    };

    // 2. Call the writer function.
    println!("Creating archive...");
    writer::create_archive(&args)?;
    
    println!("Archive created successfully!");
    Ok(())
}

Reading an Archive's File Index

To inspect an archive, the first step is to read its metadata and file index.

  • Function: reader::read_archive_metadata(path: &Path, password: Option<&str>) -> anyhow::Result<(MainHeader, Vec<FileEntry>)>
  • Description: Reads an archive's header and footer, processes the file index, and returns the header and a complete list of file entries.
  • Parameters:
    • path: A Path reference to the .g3fc archive file.
    • password: An Option<&str> containing the password if the archive is encrypted.
  • Returns: A Result containing a tuple: (MainHeader, Vec<FileEntry>).

Example:

use g3fc_rust::reader;
use std::path::Path;

fn list_archive_contents(archive_path: &str, password: Option<&str>) -> anyhow::Result<()> {
    // 1. Call the metadata reader function.
    let (header, file_index) = reader::read_archive_metadata(Path::new(archive_path), password)?;

    println!("Archive Version: {}.{}", header.format_version_major, header.format_version_minor);
    println!("Found {} entries in the index.", file_index.len());

    // The index contains all chunks. You would typically group them by 
    // chunk_group_id to represent logical files.
    for entry in file_index.iter().filter(|e| e.chunk_index == 0) {
        println!("- Path: {}, Size: {}", entry.path, entry.uncompressed_size);
    }
    
    Ok(())
}

Extracting Files

The easiest way to perform a complete operation like extraction is to use the functions in the commands module, which are designed for this purpose.

  • Function: commands::extract_single_file(args: &ExtractSingleArgs) -> anyhow::Result<()>
  • Description: Extracts a single logical file from an archive.
  • Parameters:
    • args: A reference to an ExtractSingleArgs struct containing the archive path, the path of the file to extract, the output directory, and an optional password.

Example:

use g3fc_rust::commands;
use g3fc_rust::ExtractSingleArgs;
use std::path::PathBuf;

fn extract_one_file() -> anyhow::Result<()> {
    // 1. Define the arguments for extracting a single file.
    let args = ExtractSingleArgs {
        archive_path: PathBuf::from("./my_archive.g3fc"),
        file_in_archive: "my_documents/report.docx".to_string(),
        output: PathBuf::from("./extracted_files"),
        password: Some("a-strong-password".to_string()),
    };

    // 2. Call the command function to perform the extraction.
    println!("Extracting '{}'...", &args.file_in_archive);
    commands::extract_single_file(&args)?;

    println!("File extracted successfully.");
    Ok(())
}
Commit count: 0

cargo fmt