ergonomic-windows

Crates.ioergonomic-windows
lib.rsergonomic-windows
version0.1.0
created_at2025-12-29 16:34:43.023022+00
updated_at2025-12-29 16:34:43.023022+00
descriptionErgonomic, safe Rust wrappers for Windows APIs - handles, processes, registry, file system, UI controls, Direct2D graphics, and more
homepagehttps://pegasusheavy.github.io/ergonomic-windows/
repositoryhttps://github.com/pegasusheavy/ergonomic-windows
max_upload_size
id2010878
size397,632
Joseph R. Quinn (quinnjr)

documentation

https://docs.rs/ergonomic-windows

README

ergonomic-windows

Crates.io Documentation License CI Security Audit

Ergonomic, safe Rust wrappers for Windows APIs โ€” handles, processes, registry, file system, and UTF-16 strings with zero-cost abstractions.

๐Ÿ“– Documentation | ๐Ÿ“š API Reference

Features

  • ๐Ÿ›ก๏ธ Safe by Default โ€” RAII wrappers automatically manage Windows handles
  • ๐Ÿ”ค Zero-Cost Strings โ€” Small string optimization for UTF-16 conversions (no heap allocation for strings โ‰ค22 chars)
  • โšก High Performance โ€” Object pooling and optimized allocations for high-throughput scenarios
  • ๐ŸŽฏ Ergonomic API โ€” Fluent builders and idiomatic Rust patterns
  • ๐Ÿ“ Rich Error Handling โ€” Typed errors with Windows error code context
  • ๐Ÿงช Well Tested โ€” 80+ tests covering edge cases, Unicode, and stress scenarios

Modules

Module Description
string UTF-8 โ†” UTF-16 conversion with small string optimization and object pooling
handle RAII wrappers for Windows HANDLE with automatic cleanup
process Process creation, management, and querying
registry Windows Registry read/write with type-safe values
fs Windows-specific file system operations
window Window creation and message handling
error Rich error types with Windows error code support

Installation

Add to your Cargo.toml:

[dependencies]
ergonomic-windows = "0.1"

Or use cargo:

cargo add ergonomic-windows

Quick Start

use ergonomic_windows::prelude::*;

fn main() -> Result<()> {
    // Spawn a process
    let exit_code = Command::new("cmd.exe")
        .args(["/c", "echo", "Hello from Rust!"])
        .no_window()
        .run()?;
    println!("Exit code: {}", exit_code);

    // Read from the registry
    let key = Key::open(
        RootKey::CURRENT_USER,
        r"Software\Microsoft\Windows\CurrentVersion\Explorer",
        Access::READ,
    )?;

    if let Ok(value) = key.get_value("ShellState") {
        println!("ShellState: {:?}", value);
    }

    Ok(())
}

Usage Examples

String Conversion

Convert between Rust UTF-8 strings and Windows UTF-16 strings:

use ergonomic_windows::string::{to_wide, from_wide, WideString};

// Basic conversion
let wide = to_wide("Hello, Windows! ๐ŸŽ‰");
let back = from_wide(&wide)?;
assert_eq!(back, "Hello, Windows! ๐ŸŽ‰");

// WideString for Windows API calls
let ws = WideString::new("C:\\Windows\\System32");
// ws.as_pcwstr() returns PCWSTR for Windows APIs

// Small strings are stored inline (no heap allocation!)
let small = WideString::new("Hello");
assert!(small.is_inline()); // true for strings โ‰ค22 UTF-16 chars

High-Throughput String Pool

For scenarios converting many strings, use the object pool to reuse buffers:

use ergonomic_windows::string::WideStringPool;

let mut pool = WideStringPool::new();

for filename in &["file1.txt", "file2.txt", "file3.txt"] {
    let wide = pool.get(filename);
    // Use wide.as_pcwstr() with Windows APIs
    pool.put(wide); // Return buffer for reuse
}

Handle Management

Windows handles are automatically closed when dropped:

use ergonomic_windows::handle::OwnedHandle;
use ergonomic_windows::fs::OpenOptions;

// Open a file - handle is automatically managed
let handle = OpenOptions::new()
    .read(true)
    .open("file.txt")?;

// Clone handles safely
let cloned = handle.try_clone()?;

// Handles close automatically when dropped

Process Management

Create and manage Windows processes:

use ergonomic_windows::process::{Command, Process, ProcessAccess};

// Spawn a process
let process = Command::new("notepad.exe")
    .arg("document.txt")
    .current_dir("C:\\Users\\Public")
    .env("MY_VAR", "value")
    .spawn()?;

println!("Started process with PID: {}", process.pid());

// Wait with timeout
use std::time::Duration;
match process.wait_timeout(Some(Duration::from_secs(5))) {
    Ok(exit_code) => println!("Exited with: {}", exit_code),
    Err(_) => {
        process.terminate(1)?;
        println!("Process terminated");
    }
}

// Open existing process
let current = Process::open(process.pid(), ProcessAccess::QUERY)?;
println!("Is running: {}", current.is_running()?);

Registry Access

Read and write Windows Registry values:

use ergonomic_windows::registry::{Key, RootKey, Access, Value};

// Read system information
let key = Key::open(
    RootKey::LOCAL_MACHINE,
    r"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
    Access::READ,
)?;

if let Ok(Value::String(name)) = key.get_value("ProductName") {
    println!("Windows Version: {}", name);
}

// Write application settings
let app_key = Key::create(
    RootKey::CURRENT_USER,
    r"Software\MyApp\Settings",
    Access::ALL,
)?;

app_key.set_value("Volume", &Value::dword(75))?;
app_key.set_value("Username", &Value::string("Alice"))?;
app_key.set_value("RecentFiles", &Value::MultiString(vec![
    "doc1.txt".into(),
    "doc2.txt".into(),
]))?;

// Enumerate keys and values
for subkey in app_key.subkeys()? {
    println!("Subkey: {}", subkey);
}

File System Operations

Windows-specific file operations:

use ergonomic_windows::fs::{
    get_attributes, set_attributes, FileAttributes,
    exists, is_dir, is_file, delete_file,
    move_file, move_file_with_options, MoveOptions,
    get_system_directory, get_temp_directory,
};

// Check file attributes
let attrs = get_attributes("C:\\Windows")?;
assert!(attrs.is_directory());

// Get system paths
let system_dir = get_system_directory()?;
let temp_dir = get_temp_directory()?;
println!("System: {:?}", system_dir);
println!("Temp: {:?}", temp_dir);

// Move with options
move_file_with_options(
    "old_path.txt",
    "new_path.txt",
    MoveOptions::new().replace().allow_copy(),
)?;

Window Creation

Create windows and handle messages:

use ergonomic_windows::window::{WindowBuilder, MessageHandler, Message};
use ergonomic_windows::prelude::*;

struct MyHandler;

impl MessageHandler for MyHandler {
    fn on_create(&mut self, hwnd: windows::Win32::Foundation::HWND) -> Result<()> {
        println!("Window created!");
        Ok(())
    }

    fn on_destroy(&mut self, _hwnd: windows::Win32::Foundation::HWND) -> Result<()> {
        std::process::exit(0);
    }
}

let window = WindowBuilder::new()
    .title("My Window")
    .size(800, 600)
    .style(Style::OVERLAPPEDWINDOW)
    .build(MyHandler)?;

window.show(ShowCommand::Show);
Message::run_loop();

Safety

This crate uses unsafe code to interface with Windows APIs. All unsafe blocks are:

  • Documented with safety invariants
  • Minimal in scope
  • Audited for correctness

The public API is entirely safe Rust. Handles are managed via RAII, preventing:

  • Use-after-close bugs
  • Double-close bugs
  • Handle leaks

Performance

The crate is optimized for performance:

Optimization Impact
Small String Optimization Zero allocation for strings โ‰ค22 chars
Object Pooling Reusable buffers for high-throughput scenarios
Pre-allocated Buffers Reduced allocations in string builders
Inline Hints Hot paths marked for inlining

Benchmark results (typical):

  • WideString::new("Hello"): 0 allocations, ~12ns
  • to_wide / from_wide: 1 allocation each
  • String pool reuse: 0 allocations after warmup

Minimum Supported Rust Version

This crate requires Rust 1.70 or later.

Contributing

Contributions are welcome! Please see our Contributing Guidelines.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development

# Run tests
cargo test

# Run benchmarks
cargo bench

# Run clippy
cargo clippy --all-targets

# Build docs
cargo doc --open

License

Licensed under either of:

at your option.

Acknowledgments

Built with the excellent windows-rs crate from Microsoft.


Made with โค๏ธ by Pegasus Heavy Industries

Commit count: 0

cargo fmt