win-shared-memory 0.1.0

A library to easily access windows shared memory.
<div align="center">

# win-shared-memory

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/dSyncro/win-shared-memory/blob/main/LICENSE)
![Version](https://img.shields.io/badge/version-0.1.0-green)
[![Crates.io](https://img.shields.io/crates/v/win-shared-memory.svg)](https://crates.io/crates/win-shared-memory)
[![docs.rs](https://docs.rs/win-shared-memory/badge.svg)](https://docs.rs/win-shared-memory)

A typed, RAII Rust library for easy access to named Windows shared memory regions.

</div>

## Table of Contents

- [Dependencies and requirements]#dependencies-and-requirements
- [Getting started]#getting-started
- [Usage]#usage
  - [Creating a region (writer process)]#creating-a-region-writer-process
  - [Opening a region (reader process)]#opening-a-region-reader-process
  - [Opening an existing region for read-write]#opening-an-existing-region-for-read-write
- [Access modes]#access-modes
- [Error handling]#error-handling
- [Safety]#safety
- [Side notes]#side-notes

## Dependencies and requirements

- **Windows only** — uses Win32 file-mapping APIs (`CreateFileMappingW`, `MapViewOfFile`, etc.).
- Requires Rust edition 2024.

## Getting started

Add the library to your project:

```bash
cargo add win-shared-memory
```

## Usage

All access goes through `SharedMemoryLink<T, Access>`, a typed RAII handle that unmaps the view
and closes the handle automatically on drop. The type `T` describes the layout of the shared
region and must be `#[repr(C)]` (or another stable layout) so that both processes agree on the
memory layout.

### Creating a region (writer process)

```rust
use win_shared_memory::{SharedMemoryLink, ReadWrite};

#[repr(C)]
struct GameState {
    score: u32,
    lives: u8,
}

// Create a fresh, zero-initialised region. Fails if the name is already taken.
let mut link: SharedMemoryLink<GameState, ReadWrite> =
    SharedMemoryLink::create("Local\\my_game_state").expect("failed to create shared memory");

unsafe {
    let state = link.get_mut();
    state.score = 42;
    state.lives = 3;
}
```

Use `get_or_create` instead if you want to open the region when it already exists:

```rust
let mut link: SharedMemoryLink<GameState, ReadWrite> =
    SharedMemoryLink::get_or_create("Local\\my_game_state").unwrap();
```

### Opening a region (reader process)

```rust
use win_shared_memory::{SharedMemoryLink, ReadOnly};

#[repr(C)]
struct GameState {
    score: u32,
    lives: u8,
}

let link: SharedMemoryLink<GameState, ReadOnly> =
    SharedMemoryLink::open("Local\\my_game_state").expect("game not running");

let state = unsafe { link.get() };
println!("score: {}, lives: {}", state.score, state.lives);
```

### Opening an existing region for read-write

A second writer (or any process that did not create the region) can open it for read-write access:

```rust
use win_shared_memory::{SharedMemoryLink, ReadWrite};

let mut link: SharedMemoryLink<GameState, ReadWrite> =
    SharedMemoryLink::open_existing("Local\\my_game_state").expect("region not found");

unsafe { link.get_mut().score += 1; }
```

## Access modes

| Type parameter | Constructor(s) | Available methods |
|----------------|----------------|-------------------|
| `ReadOnly`  | `SharedMemoryLink::open` | `get` |
| `ReadWrite` | `SharedMemoryLink::create`, `SharedMemoryLink::get_or_create`, `SharedMemoryLink::open_existing` | `get`, `get_mut` |

## Error handling

All constructors return `Result<_, SharedMemoryError>`. The enum variants are:

| Variant | When |
|---------|------|
| `OpenMapping(windows::core::Error)` | `OpenFileMappingW` failed (region not found, access denied) |
| `CreateMapping(windows::core::Error)` | `CreateFileMappingW` failed |
| `MapView(windows::core::Error)` | `MapViewOfFile` returned null |
| `AlreadyExists` | `create` was called but the name is already taken |
| `SizeTooLarge` | `size_of::<T>()` exceeds `u32::MAX` |

## Safety

`get` and `get_mut` are `unsafe` because shared memory is inherently a cross-process resource.
The library enforces single-process aliasing rules through Rust's borrow checker (`get_mut`
requires `&mut self`), but it cannot prevent a remote process from writing concurrently.

Callers are responsible for coordinating cross-process access — for example with a
[named mutex](https://learn.microsoft.com/en-us/windows/win32/sync/using-named-objects).

## Side notes

Please keep in mind that at the moment this is a side project developed with no planned continuity
nor schedule. Therefore _support, fixes and new features can not be guaranteed_.

As stated in the [LICENSE](https://github.com/dSyncro/win-shared-memory/blob/main/LICENSE),
_no contributor must be considered liable for the use of this project_.