# Configuration and Device Contract
This document describes the public configuration surface for release users.
Longer implementation notes remain in `docs/architecture.md`; this file is the
short operational contract.
## Features
The default feature set enables `std` and exports `FileBlockDevice`.
```toml
[dependencies]
littlefs-rust = { package = "littlefs2-rust", version = "0.1" }
```
For `no_std` targets, disable default features. The library still depends on
`alloc`, so the final firmware must provide a global allocator.
```toml
[dependencies]
littlefs-rust = { package = "littlefs2-rust", version = "0.1", default-features = false }
```
## Physical Geometry
`Config` contains only the physical image geometry:
```rust
use littlefs_rust::Config;
let cfg = Config {
block_size: 512,
block_count: 4096,
};
```
The block size and block count must match the image being mounted. The
superblock is still parsed and checked after mount.
## Filesystem Options
`FilesystemOptions` mirrors the main non-callback fields of C littlefs'
`struct lfs_config`. The simple APIs use `FilesystemOptions::default()`;
the `*_with_options` APIs accept caller-provided values:
- `Filesystem::format_device_with_options`
- `Filesystem::mount_device_with_options`
- `Filesystem::mount_device_mut_with_options`
- `Filesystem::mount_with_options`
Supported fields:
| `read_size` | Minimum aligned read unit used for config validation and cache geometry. |
| `prog_size` | Minimum aligned program unit used by metadata commits and config validation. |
| `cache_size` | Parser/cache chunk target; clamped to the block size where appropriate. |
| `lookahead_size` | Accepted and validated to match C config shape. The current allocator still uses an in-memory bitmap plus a fixed internal scan window. |
| `block_cycles` | Metadata relocation cadence. `None` disables block-cycle relocation. |
| `name_max` | Maximum file or directory name length recorded in the superblock. |
| `file_max` | Maximum file size recorded in the superblock and checked by write paths. |
| `attr_max` | Maximum user attribute size recorded in the superblock and checked by attr writes. |
| `metadata_max` | Optional metadata-pair working limit used for validation and inline threshold derivation. |
| `inline_max` | Inline-file policy, represented by `InlineMax`. |
Example:
```rust
use littlefs_rust::{FilesystemOptions, InlineMax};
let options = FilesystemOptions {
read_size: 16,
prog_size: 16,
cache_size: 128,
block_cycles: Some(256),
metadata_max: Some(512),
inline_max: InlineMax::Limit(64),
..FilesystemOptions::default()
};
```
Validation follows the littlefs relationships that are visible through the
public API:
- `read_size`, `prog_size`, `cache_size`, and `lookahead_size` must be nonzero.
- `cache_size` must be divisible by `read_size` and `prog_size`.
- `block_size` must be divisible by the effective cache size.
- `prog_size` must be a power of two.
- `lookahead_size` must be byte-aligned to a multiple of 8.
- `block_cycles = Some(0)` is rejected.
- `name_max`, `file_max`, and `attr_max` must be nonzero and inside the
littlefs-compatible maxima.
- `metadata_max`, when present, must divide the block geometry and align to
read/program sizes.
## Inline Policy
`InlineMax` avoids exposing C's sentinel integer values directly:
| `InlineMax::Default` | Derive C's default inline threshold from cache, attr, and metadata limits. |
| `InlineMax::Disabled` | Disable non-empty inline file data. |
| `InlineMax::Limit(n)` | Use an explicit inline threshold after validation. |
## Block Device Contract
Implementors provide four operations:
```rust
use littlefs_rust::{BlockDevice, Config, Result};
struct MyFlash;
impl BlockDevice for MyFlash {
fn config(&self) -> Config {
Config {
block_size: 512,
block_count: 4096,
}
}
fn read(&self, block: u32, off: usize, out: &mut [u8]) -> Result<()> {
todo!()
}
fn prog(&mut self, block: u32, off: usize, data: &[u8]) -> Result<()> {
todo!()
}
fn erase(&mut self, block: u32) -> Result<()> {
todo!()
}
fn sync(&mut self) -> Result<()> {
Ok(())
}
}
```
Rules:
- `read` and `prog` operate within one logical block. Cross-block requests are
invalid.
- `prog` should model flash programming: bits can move from `1` to `0` without
erase, but not from `0` back to `1`.
- `erase` resets one whole block to the erased state expected by littlefs,
normally `0xff`.
- `sync` should flush backend state when the platform has a separate durable
boundary. It may be a no-op for synchronous memory-mapped or test devices.
`MemoryBlockDevice` and `FileBlockDevice` both follow these rules and are used
by integration tests as real backends.
## Full-Image Utilities
`Filesystem::mount(&[u8])`, `ImageBuilder`, and `ImageEditor` are useful for
fixtures, corruption tests, and host tools that already own a complete image.
Mounted production-style code should prefer `mount_device` or
`mount_device_mut`, because those paths avoid resident capacity-sized image
ownership.