| Crates.io | large-text-viewer |
| lib.rs | large-text-viewer |
| version | 0.1.1 |
| created_at | 2025-12-14 18:05:59.479031+00 |
| updated_at | 2025-12-15 06:02:56.613067+00 |
| description | A high-performance viewer for large text files |
| homepage | |
| repository | https://github.com/acejarvis/large-text-viewer |
| max_upload_size | |
| id | 1984830 |
| size | 939,428 |
ECE1724 Rust Course Project Final Report
In domains such as systems programming, data science, and DevOps, developers frequently interact with massive text files—server logs, database dumps, and simulation outputs—that can easily exceed gigabytes in size. Modern code editors like Visual Studio Code and Zed are optimized for code editing (AST parsing, syntax highlighting) rather than raw data throughput. Consequently, attempting to open a multi-gigabyte file often results in the editor freezing or crashing due to excessive memory consumption. This is a well-documented issue in the Zed editor community (see Issue #4701).
Users are often forced to resort to command-line tools like less or grep, which, while efficient, lack the interactivity and convenience of a graphical user interface. There is a clear need for a tool that combines the performance of CLI utilities with the usability of a modern GUI. This project was motivated by the desire to solve this practical pain point using Rust's zero-cost abstractions and memory safety guarantees.
The primary objective of this project was to develop a high-performance GUI application capable of handling text files larger than 4GB with minimal resource usage. Specifically, the goals were:
The project serves as both a standalone application (crate: large-text-viewer) and a proof-of-concept backend (crate: large-text-core) for a future extension to the Zed editor.

The final deliverable offers the following key features:
memmap2 to treat files as memory slices, allowing the OS to handle paging. This enables opening files larger than available RAM.The application follows a modular architecture, separating the core file processing logic from the user interface. This separation of concerns facilitates testing and future integration into other platforms (e.g., as a Zed extension).
The system is divided into two primary layers:
Core Layer (large-text-core):
FileReader: Manages memory-mapped file access using the memmap2 crate. It handles encoding detection and decoding, presenting a unified interface for byte-level access.LineIndexer: Responsible for mapping line numbers to byte offsets. It implements the hybrid indexing strategy to balance memory usage and access speed.SearchEngine: A parallelized search module that scans the memory-mapped file in chunks.Replacer: Handles file modifications, ensuring data integrity through copy-on-write mechanisms.UI Layer (large-text-viewer):
egui, an immediate mode GUI library for Rust.TextViewerApp: The main application state manager. It handles user input, manages the viewport (virtual scrolling), and coordinates asynchronous tasks (search, replace) via channels.%%{init: {'flowchart': {'curve': 'step'}}}%%
flowchart TD
main["main.rs<br>entrypoint"] --> app["TextViewerApp<br>(app.rs)"]
subgraph UI [egui]
menu["Menu/Toolbar/Status/Dialogs"]
viewport["Central text area<br>(show_rows, wrap, highlights, line nos)"]
end
subgraph Core [Core]
fr["FileReader<br>memmap + decoding"]
li["LineIndexer<br>full/sparse offsets"]
se["SearchEngine<br>chunked literal/regex"]
watcher["Tail watcher<br>(notify)"]
end
app --> menu
app --> viewport
app --> fr
app --> li
app --> se
app --> watcher
fr --> li
fr --> se
li --> viewport
se --> viewport
menu -->|open file| app
menu -->|encoding select| app
menu -->|search actions| app
menu -->|tail toggle| watcher
The application relies heavily on asynchronous communication to keep the UI responsive.
SearchEngine, which spawns threads. Results are streamed back to the UI via a mpsc channel (SearchMessage::CountResult, SearchMessage::ChunkResult), allowing the UI to update progress bars and highlight matches in real-time without blocking the render loop.sequenceDiagram
participant UI as UI (toolbar/status)
participant App as TextViewerApp
participant Reader as FileReader
participant Indexer as LineIndexer
participant Search as SearchEngine
UI->>App: perform_search(query, regex?)
App->>Search: set_query()
App->>Search: count_matches(Reader, channel)
loop Search Thread
Search->>Reader: get_bytes(chunk)
Search-->>App: SearchMessage::CountResult
end
App->>UI: status "Found N matches"
UI->>App: next/prev
App->>Search: fetch_matches(Reader, channel)
Search-->>App: SearchMessage::ChunkResult
App->>UI: scroll_to_row(target line)
App->>Indexer: get_line(line)
Indexer->>Reader: get_bytes(span)
App->>UI: render line with inline highlights
Rendering: The UI requests only the lines currently visible in the viewport. The LineIndexer calculates the byte ranges, and the FileReader decodes only those specific bytes from the memory map.
To install the application via Cargo, run the following command in your terminal (Windows, macOS, or Linux):
cargo install large-text-viewer
Once installed, start the application by typing:
large-text-viewer
The instructor can follow these steps to build and run the project on Ubuntu Linux or macOS.
Ensure the Rust toolchain is installed:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
Clone this repo, navigate to the project root directory and build in release mode for optimal performance:
cd large-text-viewer
cargo build --release
To test the large file capabilities, you can use the provided script to generate a large dummy file (e.g., 1GB):
# Make the script executable
chmod +x scripts/generate_test_files.sh
# Run the script (generates files in a 'test_files' directory)
./scripts/generate_test_files.sh
Note: This script creates a few files of varying sizes for testing purposes.
Or just simply run the unit test:
cargo test --workspace
Execute the binary:
cargo run --release
Or run the binary directly from the target folder:
./target/release/large-text-viewer
Jarvis Wang (Solo Project)
Core Logic: Designed and implemented the large-text-core library, including the FileReader (memmap2 integration), LineIndexer (hybrid sparse indexing algorithm), SearchEngine (multi-threaded chunk search), and Replacer (streaming copy-on-write logic).
User Interface: Built the large-text-viewer GUI using egui, implementing the virtual viewport rendering, event handling, and asynchronous state management.
Testing & Documentation: Wrote unit tests for core components, created the architecture documentation, and conducted performance benchmarking.
CI/CD: Built GitHub Actions workflows for automated testing, linting (clippy, cloc), and cross-platform builds (Windows, macOS, Ubuntu) to ensure code quality and portability as well as the release workflows to publish the app and crate packages to the crates.io registry.
Strings only for the visible viewport.std::sync::mpsc channels was essential for a smooth user experience.The "Large Text Viewer" project successfully demonstrates that Rust's zero-cost abstractions and memory safety guarantees make it an ideal language for high-performance systems tools. By combining memory-mapped I/O with a sparse indexing strategy, we created a tool that outperforms standard editors by orders of magnitude when handling large files. The project meets all primary objectives, delivering a robust, memory-efficient, and responsive application.
Large Text Viewer Slide Presentation