# ps-mem Design Document
## 1. Introduction
This document describes the software design for the `ps-mem` command-line utility. It maps the functional requirements and acceptance criteria outlined in `specs/1.acceptance-criteria.md` to the components and modules within the `src` directory of the codebase.
## 2. High-Level Architecture
The application follows a modular architecture, separating concerns into distinct Rust modules. The high-level flow is as follows:
1. **Entry Point**: `main.rs` serves as the application entry point. It collects command-line arguments from the operating system.
2. **Library Facade**: The arguments are passed to the `execute` function in `lib.rs`, which acts as a facade for the library's functionality.
3. **Configuration Parsing**: The `conf` module is responsible for parsing the raw arguments into a structured `CmdOptConf` configuration object.
4. **Core Logic Execution**: The `run` module takes the configuration object and executes the main application logic, either listing processes or invoking a subprocess.
5. **Utility Functions**: The `util` module provides shared functionalities like error handling and custom data types used across the application.
## 3. Component Breakdown
### 3.1. `main.rs`
* **Responsibility**: The primary executable entry point.
* **Functionality**:
* Initializes memory management (`memx_cdy::memx_init`).
* Collects command-line arguments from `std::env::args()`.
* Invokes `libps_mem::execute` with the processed arguments.
* Handles top-level errors by printing them to `stderr` and exiting with a non-zero status code.
### 3.2. `lib.rs`
* **Responsibility**: The public library interface.
* **Functionality**:
* Defines the main modules: `conf`, `run`, `util`.
* Provides the `execute` function, which orchestrates the application flow by calling the configuration parser and then the core run logic.
* Decouples the main binary from the library's internal implementation.
### 3.3. `conf` module
* **Responsibility**: Manages all configuration-related tasks.
* **Files**: `mod.rs`, `parse.rs`
* **Functionality**:
* Defines the `CmdOptConf` struct, which holds all parsed command-line options.
* The `parse_cmdopts` function uses the `flood-tide` crate to parse `&[&str]` arguments into the `CmdOptConf` struct.
* It is responsible for handling `--help` and `--version` flags directly, returning appropriate messages.
### 3.4. `run` module
* **Responsibility**: Contains the core application logic.
* **Files**: `run.rs`
* **Functionality**:
* The main `run` function determines the primary execution path based on the configuration.
* **Process Listing (`do_proc_in`, `do_proc_out_list`)**:
* Uses the `linux-procfs` crate to query the `/proc` filesystem for a list of processes and their memory details (RSS, Swap).
* Sorts the collected process data according to the `opt_sort` field in `CmdOptConf`.
* Formats and prints the process list to `stdout`.
* **Subprocess Invocation (`do_proc_invoke`, `do_proc_out_one`)**:
* If the configuration contains a command to execute, it spawns a new child process.
* It monitors the child process's memory usage in a loop until it exits.
* Uses `signal-hook` to gracefully handle `SIGINT`/`SIGTERM` signals.
### 3.5. `util` module
* **Responsibility**: Provides shared utilities.
* **Files**: `mod.rs`, `err.rs`, `opt_sort_order.rs`, `opt_uc_x_param.rs`
* **Functionality**:
* `err.rs`: Defines a `BrokenPipeError` trait to gracefully handle broken pipe errors when the output is piped to another command (e.g., `head`).
* `opt_sort_order.rs`: Defines the `OptSortOrder` enum (`Swap`, `Rss`, `Total`) used for type-safe sorting options.
* `opt_uc_x_param.rs`: Defines the `OptUcXParam` enum for advanced `-X` options.
## 4. Mapping Acceptance Criteria to Design
| UC1 | List PID, RSS, Swap, Total memory, and command. | `run::do_proc_in`, `run::do_proc_out_list`, `linux-procfs` |
| UC2 | Display memory sizes in KiB. | `run::do_proc_out_list`, `num-format` crate |
| UC3 | Provide a summary row for total memory. | `run::do_proc_out_list` |
| ED1 | Execute and monitor a specific command. | `run::do_proc_invoke` |
| ED2 | Display memory for a single PID via `--pid`. | `conf::parse_cmdopts`, `run::do_proc_in` |
| ED3 | Include all processes via `-a`/`--all`. | `conf::parse_cmdopts`, `run::do_proc_in` |
| ED4 | Sort output via `--sort`. | `conf::parse_cmdopts`, `run::do_proc_in` (sorting logic) |
| ED5 | Display full command line via `-l`/`--cmdline`. | `conf::parse_cmdopts`, `run::do_proc_in` |
| ED6 | Display help via `-H`/`--help`. | `conf::parse_cmdopts` |
| ED7 | Display version via `-V`/`--version`. | `conf::parse_cmdopts` |
| ED8 | Handle advanced options via `-X`. | `conf::parse_cmdopts` |