ps-mem 0.3.2

The process memory size listing
Documentation
# 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

| ID  | Acceptance Criterion                                        | Implementing Component(s)                                     |
|-----|-------------------------------------------------------------|---------------------------------------------------------------|
| 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`                                         |