# 機能設計書 43-CSV/TSV

## 概要

本ドキュメントは、NushellにおけるCSV/TSV形式のデータ変換機能（`from csv`, `to csv`, `from tsv`, `to tsv`コマンド）の詳細設計を記載する。これらのコマンドは、カンマ区切り（CSV）およびタブ区切り（TSV）のテキストデータとNushellテーブル間の相互変換を提供する。

### 本機能の処理概要

CSV/TSV変換機能は、表形式データの最も一般的な交換フォーマットの読み書きを提供する。スプレッドシート、データベースエクスポート、ログファイルなど、様々なソースのデータをNushellのテーブルとして操作可能にする。

**業務上の目的・背景**：CSVは表形式データの標準的な交換形式であり、Excel、Google Sheets、データベースなど多くのシステムでサポートされている。TSVは区切り文字の曖昧さが少なく、タブ区切りのデータ（UNIXツールの出力など）の処理に適している。これらのフォーマットを効率的に処理できることは、データ分析やETL処理において重要である。

**機能の利用シーン**：
- スプレッドシートからエクスポートしたCSVファイルの解析
- データベースからのエクスポートデータの処理
- ログファイルやCLIツール出力の解析（TSV形式）
- Nushellで加工したデータをCSV形式でエクスポート
- 大量データのバッチ処理

**主要な処理内容**：
1. `from csv`: CSV文字列をテーブルに変換（カスタムセパレータ、クォート、エスケープ対応）
2. `from tsv`: タブ区切りテキストをテーブルに変換
3. `to csv`: テーブルをCSV文字列に変換
4. `to tsv`: テーブルをTSV文字列に変換
5. 空白トリミング、ヘッダー無し、柔軟なカラム数対応

**関連システム・外部連携**：内部的にcsvクレートを使用してパース・シリアライズを行う。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLI専用機能のため画面なし |

## 機能種別

データ変換 / フォーマット変換

## 入力仕様

### 入力パラメータ

#### from csv

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | String | Yes | CSV文字列（パイプライン入力） | テキスト形式 |
| --separator / -s | String | No | 区切り文字（1文字または4バイトUnicode） | デフォルト: `,` |
| --comment / -c | String | No | コメント開始文字 | 1文字 |
| --quote / -q | String | No | クォート文字 | デフォルト: `"` |
| --escape / -e | String | No | エスケープ文字 | 1文字 |
| --noheaders / -n | Switch | No | 最初の行をヘッダーとして扱わない | - |
| --flexible | Switch | No | 行ごとに異なるカラム数を許容 | - |
| --no-infer | Switch | No | 型推論を行わない | - |
| --trim / -t | String | No | 空白トリミングオプション | all/fields/headers/none |

#### from tsv

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | String | Yes | TSV文字列（パイプライン入力） | テキスト形式 |
| --comment / -c | String | No | コメント開始文字 | 1文字 |
| --quote / -q | String | No | クォート文字 | デフォルト: `"` |
| --escape / -e | String | No | エスケープ文字 | 1文字 |
| --noheaders / -n | Switch | No | 最初の行をヘッダーとして扱わない | - |
| --flexible | Switch | No | 行ごとに異なるカラム数を許容 | - |
| --no-infer | Switch | No | 型推論を行わない | - |
| --trim / -t | String | No | 空白トリミングオプション | all/fields/headers/none |

#### to csv

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | record / table | Yes | 変換対象データ（パイプライン入力） | レコードまたはテーブル |
| --separator / -s | String | No | 区切り文字 | デフォルト: `,` |
| --noheaders / -n | Switch | No | ヘッダー行を出力しない | - |
| --columns | List[String] | No | 出力するカラム名と順序 | - |

#### to tsv

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | record / table | Yes | 変換対象データ（パイプライン入力） | レコードまたはテーブル |
| --noheaders / -n | Switch | No | ヘッダー行を出力しない | - |
| --columns | List[String] | No | 出力するカラム名と順序 | - |

### 入力データソース

パイプライン入力（from: String型、to: record/table型）

## 出力仕様

### 出力データ

#### from csv / from tsv

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | table | 変換後のテーブル |

#### to csv / to tsv

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | String | CSV/TSV形式の文字列 |

### 出力先

標準出力（パイプライン出力）。to csv/tsvはcontent_typeメタデータを付与（text/csv、text/tab-separated-values）。

## 処理フロー

### 処理シーケンス

```
from csv/tsv:
1. パイプライン入力を受け取る
   └─ String型を期待（リスト入力はエラー）
2. 設定パラメータを解析
   └─ separator, comment, quote, escape等
3. DelimitedReaderConfigを構築
   └─ 各オプションを設定構造体に格納
4. from_delimited_data関数を呼び出し
   └─ csvクレートでパース
5. 型推論を適用（--no-inferが未指定の場合）
6. テーブルとして出力

to csv/tsv:
1. パイプライン入力を受け取る
   └─ record/table型を期待
2. 設定パラメータを解析
   └─ separator, noheaders, columns
3. to_delimited_data関数を呼び出し
   └─ csvクレートでシリアライズ
4. 文字列として出力（メタデータ付き）
```

### フローチャート

```mermaid
flowchart TD
    subgraph from ["from csv/tsv"]
        A1[入力: String] --> B1{入力タイプ確認}
        B1 -->|List| C1[エラー: --rawフラグを使用]
        B1 -->|String| D1[DelimitedReaderConfig構築]
        D1 --> E1[from_delimited_data]
        E1 --> F1{--no-infer?}
        F1 -->|No| G1[型推論適用]
        F1 -->|Yes| H1[文字列のまま]
        G1 --> I1[テーブル出力]
        H1 --> I1
    end

    subgraph to ["to csv/tsv"]
        A2[入力: record/table] --> B2[separator設定]
        B2 --> C2{--columns指定?}
        C2 -->|Yes| D2[指定カラムのみ出力]
        C2 -->|No| E2[全カラム出力]
        D2 --> F2[to_delimited_data]
        E2 --> F2
        F2 --> G2{--noheaders?}
        G2 -->|Yes| H2[ヘッダーなし]
        G2 -->|No| I2[ヘッダーあり]
        H2 --> J2[String出力 + metadata]
        I2 --> J2
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-43-01 | セパレータ形式 | 1文字または4バイトUnicodeコードポイント（16進数） | from csv --separator |
| BR-43-02 | デフォルトセパレータ | CSVはカンマ、TSVはタブ | from csv/tsv |
| BR-43-03 | ヘッダー自動認識 | 最初の行をヘッダーとして使用（--noheadersで無効化） | from csv/tsv |
| BR-43-04 | カラム名自動生成 | --noheaders時はcolumn0, column1...が使用される | from csv/tsv --noheaders |
| BR-43-05 | 柔軟カラム数 | --flexible指定時は行ごとにカラム数が異なることを許容 | from csv/tsv --flexible |
| BR-43-06 | 型推論 | 数値、日付等の型を自動推論（--no-inferで無効化） | from csv/tsv |
| BR-43-07 | タブエスケープ | セパレータに`\t`を指定するとタブに変換 | to csv --separator |
| BR-43-08 | content_type | CSVはtext/csv、TSVはtext/tab-separated-values | to csv/tsv |

### 計算ロジック

**トリムオプション**:
- `all`: ヘッダーとフィールド両方をトリム
- `headers`: ヘッダーのみトリム
- `fields`: フィールド値のみトリム
- `none`: トリムしない

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TypeMismatch | 入力エラー | リストストリームが入力された | --rawフラグでファイルを開く |
| NonUtf8Custom | セパレータエラー | セパレータが1文字/4バイトでない | 正しい形式を指定 |
| IncompatibleParametersSingle | 型エラー | セパレータが1文字でない | 正しい形式を指定 |

### リトライ仕様

リトライは不要。

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

本機能はトランザクション処理を行わない。

## パフォーマンス要件

- 大きなCSVファイルはストリーム処理される
- 型推論は全データの読み込みが必要なため、大きなファイルではメモリを消費する

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

- CSV Injectionに注意（先頭に=, +, -, @がある場合）
- 非常に長い行や多数のカラムはメモリ消費の原因となる

## 備考

- 4バイトUnicode（例: `001f`）は`u32::from_str_radix`で解析される
- TSVは固定でタブをセパレータとして使用

---

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

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

### 推奨読解順序

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

区切り文字ベースのパース設定を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | delimited.rs (from) | `crates/nu-command/src/formats/from/delimited.rs` | DelimitedReaderConfig構造体と設定オプション |
| 1-2 | delimited.rs (to) | `crates/nu-command/src/formats/to/delimited.rs` | ToDelimitedDataArgs構造体と出力処理 |

**読解のコツ**: `DelimitedReaderConfig`がパース時のすべての設定を保持。`from_delimited_data`関数が実際のパース処理を行う。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | csv.rs | `crates/nu-command/src/formats/from/csv.rs` | FromCsv構造体とrun関数 |

**主要処理フロー**:
1. **69-77行目**: run関数でfrom_csv呼び出し
2. **141-202行目**: from_csv関数で設定を構築
3. **156-171行目**: セパレータの解析（1文字or4バイトUnicode）
4. **190-199行目**: DelimitedReaderConfig構築
5. **201行目**: from_delimited_data呼び出し

#### Step 3: to csvのエントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | csv.rs | `crates/nu-command/src/formats/to/csv.rs` | ToCsv構造体とrun関数 |

**主要処理フロー**:
- **72-85行目**: run関数でフラグ取得
- **88-133行目**: to_csv関数でセパレータ処理
- **121-132行目**: to_delimited_data呼び出し

#### Step 4: TSV実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | tsv.rs (from) | `crates/nu-command/src/formats/from/tsv.rs` | FromTsv - セパレータがタブ固定 |
| 4-2 | tsv.rs (to) | `crates/nu-command/src/formats/to/tsv.rs` | ToTsv - セパレータがタブ固定 |

**読解のコツ**: TSV実装はCSVと同様だが、セパレータが`\t`で固定されている点が異なる。

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

```
from csv
    │
    ├─ FromCsv::run
    │      └─ from_csv
    │             ├─ セパレータ解析
    │             ├─ DelimitedReaderConfig構築
    │             └─ from_delimited_data
    │                    └─ csvクレート呼び出し
    │
from tsv
    │
    ├─ FromTsv::run
    │      └─ from_tsv
    │             ├─ separator = '\t' (固定)
    │             └─ from_delimited_data
    │
to csv
    │
    ├─ ToCsv::run
    │      └─ to_csv
    │             ├─ セパレータ解析
    │             └─ to_delimited_data
    │
to tsv
    │
    ├─ ToTsv::run
    │      └─ to_tsv
    │             ├─ separator = '\t' (固定)
    │             └─ to_delimited_data
```

### データフロー図

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

from csv/tsv:
String ───▶ csvクレート ───▶ Record[] ───▶ table

to csv/tsv:
table/record ───▶ csvクレート ───▶ String
                        │
                        └── content_type: text/csv or text/tab-separated-values
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| csv.rs (from) | `crates/nu-command/src/formats/from/csv.rs` | ソース | from csvコマンド実装 |
| csv.rs (to) | `crates/nu-command/src/formats/to/csv.rs` | ソース | to csvコマンド実装 |
| tsv.rs (from) | `crates/nu-command/src/formats/from/tsv.rs` | ソース | from tsvコマンド実装 |
| tsv.rs (to) | `crates/nu-command/src/formats/to/tsv.rs` | ソース | to tsvコマンド実装 |
| delimited.rs (from) | `crates/nu-command/src/formats/from/delimited.rs` | ソース | 共通パース処理 |
| delimited.rs (to) | `crates/nu-command/src/formats/to/delimited.rs` | ソース | 共通シリアライズ処理 |
