# StringBuilder Optimization: MutableBinaryViewArray<str>

## Decision

Replaced `Vec<String>` with `MutableBinaryViewArray<str>` for string building in the record decoder.

## Rationale

### Why MutableBinaryViewArray<str>?

1. **Aligned with Polars internals**: Polars' own `StringChunkedBuilder` uses `MutableBinaryViewArray<str>` internally (confirmed in polars-core-0.52.0). The type alias `MutablePlString = MutableBinaryViewArray<str>` exists in polars-arrow.

2. **Avoids per-string allocations**: The old `Vec<String>` approach required a heap allocation for every string. The view array stores small strings inline (≤12 bytes) and larger strings in contiguous buffers.

3. **Zero-copy decode path**: Using `decode_string_ref()` instead of `decode_string()` avoids allocating intermediate `String` objects - we push directly into the builder.

### Why not MutableUtf8Array<i32>?

The polars-arrow Avro reader uses `MutableUtf8Array<i32>`, which is the older offset-based format. However:
- This is legacy code that predates the BinaryView format
- Polars core has moved to BinaryView for string handling
- Our approach is more modern and aligned with current Polars

## Implementation Details

- `StringBuilder` now wraps `MutableBinaryViewArray<str>`
- `decode()` uses `decode_string_ref()` for zero-copy decoding
- Added `finish_with_validity()` for proper null handling in NullableBuilder
- UTF-8 validation happens during decode (via `std::str::from_utf8`)

## Bug Fix: Large Block Support

During testing with 100KB strings, discovered that the block reader had a 64KB buffer limit that prevented reading large blocks. Fixed by making `next_block()` retry with larger buffers when the initial read is insufficient.

## Test Coverage

Added tests for MutableBinaryViewArray edge cases:
- Small strings (<12 bytes) - inlined in view
- Exactly 12 bytes - boundary case
- 13 bytes - just over inline limit
- 100KB strings - large buffer storage + block reader fix

## Performance

Benchmark results on `large_wide` (1M records, 100 columns):
- jetliner_open: 2.541s ± 0.044s
- jetliner_scan: 2.467s ± 0.027s

The optimization contributes to overall string handling efficiency, though the benchmark includes many column types.
