# 機能設計書 35-IOストリーム

## 概要

本ドキュメントは、Julia Base ライブラリにおけるIOストリーム機能の設計を記述する。`IO` / `IOStream` / `IOBuffer` / `IOContext` による基本的なストリームI/O（`read` / `write` / `seek` / `close`）を提供する。

### 本機能の処理概要

本機能は、Julia のI/Oシステムの基盤となる抽象型 `IO` と、その主要な具象実装である `IOBuffer`（メモリ内バッファ）、`IOStream`（ファイルベースストリーム）、`IOContext`（メタデータ付きIOラッパー）を提供する。

**業務上の目的・背景**：あらゆるプログラムの入出力操作の基盤として、統一されたストリームインターフェースを提供する。ファイル読み書き、ネットワーク通信、メモリバッファ操作、文字列構築など、すべてのI/O操作が `IO` 抽象型を通じて多態的に処理される。

**機能の利用シーン**：ファイルの読み書き、文字列の構築（sprint等）、バイナリデータの処理、I/Oコンテキスト（表示幅、コンパクトモード等）の伝播、バッファリングされたI/O操作。

**主要な処理内容**：
1. `IO` 抽象型と基本インターフェース（`read`, `write`, `seek`, `close`, `flush` 等）
2. `GenericIOBuffer{T}` / `IOBuffer` によるメモリ内バッファI/O
3. `IOStream` によるファイルベースのストリームI/O
4. `IOContext` によるメタデータ付きI/Oラッパー
5. `PipeBuffer` による非シーク可能パイプバッファ
6. `take!` / `takestring!` によるバッファ内容の取得
7. `seek` / `seekstart` / `seekend` / `skip` / `position` によるポジション操作
8. `mark` / `reset` / `unmark` によるマーク機構
9. `ensureroom` / `compact!` によるバッファメモリ管理

**関連システム・外部連携**：libuv（非同期I/O）、C ランタイムライブラリ（IOStream の ios_* 関数群）。

**権限による制御**：該当なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | REPL | 主画面 | 標準入出力ストリームの使用 |

## 機能種別

基盤I/Oフレームワーク / バッファ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| data | Vector{UInt8} / String | No | IOBuffer の初期データ | - |
| read | Bool | No | 読み取り可能フラグ | デフォルト: data 指定時 true |
| write | Bool | No | 書き込み可能フラグ | デフォルト: data 指定時 false |
| append | Bool | No | 追記モード | デフォルト: false |
| truncate | Bool | No | 切り詰めモード | デフォルト: false |
| maxsize | Int | No | 最大バッファサイズ | デフォルト: typemax(Int) |
| sizehint | Int | No | 初期バッファサイズヒント | - |
| context | Pair / IO / IOContext | No | IOContext のメタデータ | - |

### 入力データソース

コンストラクタの引数として受け取る。IOStream はファイルシステムから、IOBuffer はメモリから。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| read結果 | UInt8 / Vector{UInt8} / T | 読み取ったデータ |
| write結果 | Int | 書き込んだバイト数 |
| take!結果 | Vector{UInt8} | バッファの内容（バッファはリセット） |
| takestring!結果 | String | バッファの内容を文字列として取得 |
| position結果 | Int | 現在のストリーム位置 |

### 出力先

read/write は指定されたストリーム経由で入出力を行う。

## 処理フロー

### 処理シーケンス

```
1. IOBuffer() の構築
   └─ GenericIOBuffer{Memory{UInt8}} を生成
   └─ data, readable, writable, seekable, append, size, maxsize, ptr 等を初期化
2. write(io::IOBuffer, byte::UInt8)
   └─ ensureroom(io, 1) で空き容量を確保
   └─ io.data[io.ptr] = byte; io.ptr += 1
   └─ io.size = max(io.size, io.ptr - 1)
3. read(io::IOBuffer, ::Type{UInt8})
   └─ io.readable チェック
   └─ io.ptr > io.size で EOFError
   └─ byte = io.data[io.ptr]; io.ptr += 1
4. take!(io::IOBuffer)
   └─ data[1:io.size] をコピー
   └─ io.reinit = true でリセット
5. ensureroom(io, nshort)
   └─ 必要に応じて compact! でデータを前方移動
   └─ 足りなければ resize! でバッファ拡張
```

### フローチャート

```mermaid
flowchart TD
    A[開始: write to IOBuffer] --> B{書き込み可能?}
    B -->|No| C[throw: not writable]
    B -->|Yes| D[ensureroom で空き確保]
    D --> E{現在の空きで十分?}
    E -->|Yes| F[データ書き込み]
    E -->|No| G{compact! 可能?}
    G -->|Yes| H[compact! でデータ前方移動]
    G -->|No| I{maxsize 超過?}
    I -->|Yes| J[throw: maxsize exceeded]
    I -->|No| K[resize! でバッファ拡張]
    H --> F
    K --> F
    F --> L[ptr, size 更新]
    L --> M[終了: 書き込みバイト数返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-35-01 | IOBuffer デフォルト | 引数なし IOBuffer() は読み書き可能・シーク可能 | IOBuffer() |
| BR-35-02 | データ指定時 | data 指定の IOBuffer はデフォルトで読み取り専用 | IOBuffer(data) |
| BR-35-03 | PipeBuffer | PipeBuffer は非シーク可能な IOBuffer | PipeBuffer() |
| BR-35-04 | IOContext 伝播 | IOContext のプロパティは内部 IO に自動伝播 | IOContext(io, pairs...) |
| BR-35-05 | take! リセット | take! 後のバッファは reinit フラグで初期化待ち | take!(io::IOBuffer) |
| BR-35-06 | compact! 条件 | seekable でなく、offset が十分大きい場合にデータを前方移動 | ensureroom 内 |

### 計算ロジック

- バッファ拡張: `newsize = min(maxsize, max(needed, min(div(maxsize, 2), ndata * 2)))` で容量を算出
- compact!: `copyto!(data, 1, data, offset+1, ndata)` でデータを前方移動

## データベース操作仕様

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | EOFError | read でバッファ末尾に到達 | データが十分にあることを確認 |
| - | ArgumentError | 書き込み不可のバッファへの write | writable=true で作成 |
| - | ArgumentError | maxsize を超える書き込み | より大きな maxsize を指定 |
| - | ArgumentError | 非シーク可能バッファへの seek | seekable=true で作成 |

### リトライ仕様

該当なし。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- IOBuffer はメモリ内操作のため、ファイルI/Oに比べて極めて高速
- `compact!` によるデータ前方移動で、PipeBuffer の継続的な読み書きでのメモリ増大を防止
- `ensureroom` の拡張戦略で、頻繁な再割り当てを回避
- IOStream はC言語の ios バッファを使用し、システムコールの呼び出し回数を削減

## セキュリティ考慮事項

該当なし。

## 備考

- `GenericIOBuffer{T}` はパラメトリック型であり、`IOBuffer = GenericIOBuffer{Memory{UInt8}}` がデフォルト
- IOStream は mutable struct で内部に 128 バイトの ios バッファ（`NTuple{128, UInt8}`）を持つ
- IOContext は `AbstractPipe` のサブタイプであり、内部の IO を直接ラップする
- `lock` / `unlock` メソッドがデフォルトで noop として定義されており、スレッドセーフなサブタイプで上書き可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | io.jl | `base/io.jl` | IO 抽象型の定義（5-10行目）と基本インターフェース |
| 1-2 | iobuffer.jl | `base/iobuffer.jl` | GenericIOBuffer 構造体: data, readable, writable, seekable, append, size, maxsize, ptr, offset_or_compacted, mark フィールド |
| 1-3 | iostream.jl | `base/iostream.jl` | IOStream 構造体: handle, ios バッファ, name, mark, lock フィールド |

**読解のコツ**: `GenericIOBuffer` の `ptr` は「次に読み書きする位置」（1-indexed）、`size` は「有効データの末尾位置」、`offset_or_compacted` は PipeBuffer での読み取り済みデータのオフセット。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | io.jl | `base/io.jl` | isopen, close, flush, isreadable, iswritable 等の基本インターフェース |
| 2-2 | iobuffer.jl | `base/iobuffer.jl` | IOBuffer コンストラクタ群: データ指定、サイズヒント指定、keyword引数 |
| 2-3 | iostream.jl | `base/iostream.jl` | IOStream の open 関数と mode 文字列解析 |

#### Step 3: IOBuffer の読み書きを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | iobuffer.jl | `base/iobuffer.jl` | write(io::GenericIOBuffer, byte::UInt8): バイト書き込み |
| 3-2 | iobuffer.jl | `base/iobuffer.jl` | read(io::GenericIOBuffer, ::Type{UInt8}): バイト読み取り |
| 3-3 | iobuffer.jl | `base/iobuffer.jl` | ensureroom / compact!: メモリ管理 |
| 3-4 | iobuffer.jl | `base/iobuffer.jl` | take! / takestring!: バッファ内容の取得 |

#### Step 4: IOContext を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | io.jl | `base/io.jl` | IOContext の定義と properties Dict の管理 |

### プログラム呼び出し階層図

```
IO (抽象型)
    |
    +-- GenericIOBuffer{T} (IOBuffer = GenericIOBuffer{Memory{UInt8}})
    |       |
    |       +-- write(io, byte::UInt8)
    |       |       +-- ensureroom(io, 1)
    |       |               +-- compact!(io) [PipeBuffer]
    |       |               +-- resize!(io.data, newsize)
    |       |
    |       +-- read(io, ::Type{UInt8})
    |       +-- seek(io, pos) / seekstart / seekend / skip
    |       +-- take!(io) / takestring!(io)
    |       +-- mark(io) / reset(io) / unmark(io)
    |
    +-- IOStream
    |       |
    |       +-- open(filename, mode)
    |       +-- read/write via ccall (ios_readall, ios_write)
    |       +-- close -> ccall(:ios_close)
    |
    +-- IOContext <: AbstractPipe
            |
            +-- IOContext(io, :key => value, ...)
            +-- get(io, :key, default)
            +-- pipe_writer(ctx) -> 内部IO
```

### データフロー図

```
[入力]                        [処理]                           [出力]

bytes: Vector{UInt8} -------> write(io::IOBuffer, bytes) --> IOBuffer 内部バッファ
                                   |
                                   +-> ensureroom(io, len)
                                   +-> copyto!(io.data, ptr, bytes)
                                   +-> ptr += len

IOBuffer -----------------> read(io::IOBuffer, len) -------> Vector{UInt8}
                                   |
                                   +-> data[ptr:ptr+len-1]
                                   +-> ptr += len

IOBuffer -----------------> take!(io::IOBuffer) -----------> Vector{UInt8}
                                   |                          (バッファ内容のコピー)
                                   +-> data[1:size] をコピー
                                   +-> reinit = true
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| io.jl | `base/io.jl` | ソース | IO 抽象型と基本インターフェース、IOContext 定義 |
| iobuffer.jl | `base/iobuffer.jl` | ソース | GenericIOBuffer/IOBuffer の実装 |
| iostream.jl | `base/iostream.jl` | ソース | IOStream の実装（ファイルベースI/O） |
| stream.jl | `base/stream.jl` | ソース | LibuvStream 等の非同期I/O基盤 |
| essentials.jl | `base/essentials.jl` | ソース | AbstractPipe 抽象型の定義 |
