# TypeSlicer
TypeSlicer は任意のバイト列ストレージを「型付きメモリアクセス層」に昇格させる Rust 2024 Edition 向けクレートです。
`repr::ByteRepr` で型のバイト表現を定義し、`storage::BytesStorage` でストレージの読み書き方法を与えることで、`Slicer<T>` の `load` / `store` だけで安全に値を交換できます。
## コアコンポーネント
### `repr::ByteRepr`
- `const SIZE: usize` / `into_bytes(self, buf: &mut [u8])` / `from_bytes(bytes: &[u8]) -> Result<Self, ReprError>` を持つトレイト。
- `SIZE` はコンパイル時計算できます。
- `ReprError::InvalidByteValue` を返すことでスカラー値の検証(例: `bool` が 0/1 のみ)を実装。
### `storage::BytesStorage`
- `get(address, size)` / `get_mut(address, size)` でバイトスライスを貸し出す責務だけを負います。
- 先読み・遅延書き込み、mmap バッファ等のバックエンドはトレイト実装で差し替え可能です。
### `Slicer<T>`
- `BytesStorage` を実装した任意の型に対し、`T: ByteRepr` について blanket impl を提供。
- `load(address)` は `BytesStorage::get` → `ByteRepr::from_bytes` を連結し、`store(address, value)` は `get_mut` → `into_bytes` を呼び出します。
## インストール
```toml
[dependencies]
type_slicer = { version = "0.1" }
```
### `no_std` で使う
```toml
[dependencies]
type_slicer = { version = "0.1", default-features = false, features = ["primitive"] }
```
- `std` feature (default) は `alloc` を transitively 有効化します。
- `alloc` なしの場合は `ArrayStorage` など固定長ストレージのみを利用できます。
## Feature 一覧
| ストレージ | `std` | `alloc` + 標準ライブラリを利用。`VecStorage` や `std` ベースのテストを有効化 |
| | `alloc` | `VecStorage` や `alloc::vec` を使うコードを有効化 |
| ByteRepr | `bool`, `char`, `uint8`, `uint16`, `uint32`, `uint64`, `uint128`, `usize`, `int8`, `int16`, `int32`, `int64`, `int128`, `isize`, `f32`, `f64`, `unit` | 各プリミティブの `ByteRepr` 実装を個別に制御 |
| ByteRepr | `array` | 任意 `[T; N]` の `ByteRepr` 実装 (`T: ByteRepr`) |
| ByteRepr | `tuple` | 1〜12 要素のタプル `ByteRepr` 実装 |
| まとめ | `primitive` | すべてのプリミティブ + `array` + `tuple` を一括有効化 (default) |
| まとめ | `speed` | `bool`/`char` 変換で検証をスキップし、定数時間判定に振り切る |
| まとめ | `all` | `default` と同義。将来的な互換確保向け |
必要な feature だけを選ぶことで、最小限の表現だけをバイナリへリンクさせられます。
ただし、使わなかった型の `ByteRepr` 実装は大抵の場合コンパイル時に除去されます。
## 付属ストレージ実装
- `ArrayStorage<const N: usize>`: `no_std` でも利用できる固定長ストレージ。`new()` / `Default` は 0 埋めで初期化します。
- `VecStorage` (`alloc` 必須): 任意長で確保し、`resize(new_len)` で後からサイズ変更できます。
どちらも `BytesStorage` を実装しているため、そのまま `Slicer<T>` として利用できます。独自ストレージを追加したい場合は `get` / `get_mut` を実装するだけで `load` / `store` が自動で解放されます。
## `ByteRepr` を自作する
`repr::ByteRepr` は公開トレイトなので、ユーザ定義型をタプルや配列に委譲して簡単に実装できます。
```rust
use type_slicer::ByteRepr;
#[derive(Clone, Copy, Debug, PartialEq, ByteRepr)]
struct Header {
kind: u8,
has_payload: bool,
payload_len: u16,
}
```
`buf` / `bytes` の長さは常に `SIZE` と等しいことはこの外側で保証されているため、境界チェックは不要です。
もし、 `Slicer` を使わずに直接呼び出す場合は、呼び出し側で長さを検証してください。
## 使用例
```rust
use type_slicer::{Slicer, VecStorage, ByteRepr};
#[derive(Clone, Copy, Debug, PartialEq, ByteRepr)]
struct Packet {
opcode: u8,
has_body: bool,
length: u16,
}
fn main() -> Result<(), type_slicer::slicer::SlicerError> {
let mut storage = VecStorage::new(32);
storage.store(0, 0xDEAD_BEEFu32)?;
storage.store(4, [1u16, 2, 3, 4])?;
storage.store(12, Packet { opcode: 7, has_body: true, length: 16 })?;
let header: u32 = storage.load(0)?;
let payload: [u16; 4] = storage.load(4)?;
let packet: Packet = storage.load(12)?;
assert_eq!(header, 0xDEAD_BEEF);
assert_eq!(payload, [1, 2, 3, 4]);
assert_eq!(packet.length, 16);
Ok(())
}
```
## 制限と設計上の割り切り
- 動的サイズ型(`Vec<T>`, スライス, trait object)は `ByteRepr` を実装できません。
- 参照やポインタを扱う場合はアドレスそのもの (`usize`) をどのように解釈するかをアプリケーション側で規定してください。
- `speed` feature を有効化すると、`bool` / `char` の検証をスキップするため未定義値が発生し得ます。