bounded-str 0.1.3

Parse, don't validate! No-std bounded string with compile-time length limits and policies
Documentation
# BoundedStr: Type-Safe Strings with Static Limits and Hybrid Storage


BoundedStr is a library for creating string types with guaranteed invariants.  
It follows the **"Parse, don't validate"** principle: once an object is created, you can trust its length, format, and encoding.

- **Hybrid Storage**: Automatic selection between stack (`StackStr`) and dynamic memory (`FlexStr`) when the byte limit is exceeded.  
- **Policy-Based Design**: You choose how to measure length (bytes or characters) and how to validate content (ASCII, AlphaNumeric, etc.) via traits.  
- **No-Std First**: Full support for embedded systems, `alloc` is required only for `FlexStr`.  

## Core Concepts


### 1. Policies


Instead of hard-coded logic, BoundedStr uses:

- **LengthPolicy**: `Bytes` (fast, O(1)) or `Chars` (Unicode-correct, O(n)).  
- **FormatPolicy**: `AllowAll`, `AsciiOnly`, or your own rules (e.g., `EmailValidator`).  

### 2. Storage Types


- **StackStr**: Always on the stack. If the string does not fit in `MAX_BYTES` — error.  
- **FlexStr**: Tries to fit on the stack, but if `alloc` is enabled and the data is large — transparently moves to the heap.  

## Key Features


- **Compile-time checks**: Checks `MIN <= MAX` at compile time via const assertions.  
- **Transactional Mutation**: `mutate()` allows modifying the string via `&mut [u8]`, rolling back if the result violates type rules.  
- **Zero-cost Deref**: Implements `Deref<Target=str>`, works like a regular string with no overhead.  
- **Security**: Supports `zeroize` for automatic memory clearing (passwords, keys) and constant-time comparison.  

## Usage


```rust
use bounded_str::{StackStr, FlexStr, Bytes, Chars, AsciiOnly};
use serde::Deserialize;

// Matrix spec-compliant types — showcase ALL crate features:

// 1. Bytes (O(1)) — Room IDs, technical strings
type RoomId     = StackStr<8, 255, 255, Bytes>; 

// 2. Chars (Unicode) — usernames with Cyrillic/emoji  
type Username   = StackStr<1, 255, 1024, Chars>; 

// 3. Bytes + AsciiOnly — device IDs, technical strings
type DeviceId   = StackStr<1, 32, 32, Bytes, AsciiOnly>;

// 4. Passwords — short, zeroize-enabled
type Password   = StackStr<8, 128, 128, Bytes>;  

// 5. JWT tokens — large buffer (2KiB)
type Token      = FlexStr<16, 2048, 2048, Bytes>; 

// 6. HTML content — large, auto heap (up to 64KiB)
type HtmlBody   = FlexStr<0, 65536, 65536, Bytes>;  

// JSON auto-validation! (parse, don't validate)
#[derive(Deserialize)]

struct LoginRequest {
    username:    Username,       // Unicode OK, 1-255 chars (1KiB buffer)
    device_id:   DeviceId,       // ASCII only, 1-32 bytes (32B buffer)
    password:    Password,       // 8-128 bytes, auto zeroize (128B buffer)
    access_token: Option<Token>, // JWT up to 2KiB buffer
    room_id:     Option<RoomId>, // Matrix room everywhere!
    html_body:   HtmlBody,       // Large HTML → auto heap
}

// Real usage — invalid JSON fails automatically!
let json = r#"{
    "username": "alexey", 
    "device_id": "DEV123",
    "password": "MySecurePass123",
    "html_body": "<p>Matrix <b>rich content</b> up to 64KiB</p>"
}"#;

let req: Result<LoginRequest, _> = serde_json::from_str(json);
// Short password or oversized HTML → serde fails instantly! No manual if-checks needed.
````

## Cargo Features


```toml
[dependencies]
bounded-str = { version = "0.1", features = ["serde", "alloc", "zeroize", "constant-time"] }
```

* **serde**: Automatic validation during deserialization.
* **alloc**: Enables `FlexStr` and dynamic memory support.
* **zeroize**: Clears the buffer when it goes out of scope (`Drop`).
* **constant-time**: Protection against timing attacks during string comparisons.

## Limitations


* By default, the stack limit is set to a reasonable size (recommended up to 4KiB).
* The `Chars` policy requires a full scan of the string during creation and mutation.

## Important Architectural Note


Although `FormatPolicy` allows checking data format (e.g., Email or Regex), remember the **"Parse, don't validate"** philosophy:

* **Complexity**: Attempting perfect Email validation via policies may produce fragile code.
* **Recommendation**: Use policies for structural constraints (length, ASCII encoding, absence of control characters).
* **Business Logic**: Deep validation (e.g., domain existence, RFC 5322 compliance) is better handled by specialized parsers that convert BoundedStr into stricter data types.