# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.0] - 2026-04-26

This release introduces `FwReaderSchema` and `FwWriterSchema` as
first-class concepts for describing record shapes. A schema owns the
internal buffers used to read or format records, which makes it cheap to
swap between schemas mid-stream — useful for fixed-width formats that
interleave records of different layouts (such as the multi-line records
described by Stata `.dct` files).

### Added

- `FwReaderSchema` and `FwReaderSchemaBuilder` describe a reusable
  reader record-shape definition.
- `FwWriterSchema` and `FwWriterSchemaBuilder` describe a reusable writer
  record-shape definition (fields, separator, global truncation policy).
- `FwReader::into_reader_for_schema` and
  `AsyncFwReader::into_reader_for_schema` swap the schema driving an
  active reader without losing position in the underlying source. The
  previous schema is returned alongside the new reader so its buffers can
  be reused on a future swap with no reallocation.
- `FwWriter::into_writer_for_schema` and
  `AsyncFwWriter::into_writer_for_schema` provide the same swap
  capability on the writer side.

### Changed

- **Breaking:** `FwReaderBuilder` is renamed to `FwReaderOptions`.
- **Breaking:** `FwReader::options` (formerly `FwReader::builder`) now
  takes a pre-built `FwReaderSchema` instead of a record width. The schema
  carries the width, fields, and separator.
- **Breaking:** `FwWriterBuilder` is renamed to `FwWriterOptions`.
- **Breaking:** `FwWriter::options` (formerly `FwWriter::builder`) now
  takes a pre-built `FwWriterSchema`. The schema carries the fields,
  separator, and truncation policy.
- **Breaking:** Reader terminal methods (`from_reader`, `from_file`,
  `from_tokio_reader`, `from_tokio_file`) are now infallible. Field-bounds
  validation moved to `FwReaderSchemaBuilder::build`.

### Removed

- **Breaking:** `FwReaderOptions::field` and `FwReaderOptions::separator`
  are gone — configure these on `FwReaderSchemaBuilder` instead.
- **Breaking:** `FwReaderOptions::into_schema` is gone — build schemas
  directly via `FwReaderSchema::builder`.
- **Breaking:** `FwWriterOptions::field`, `FwWriterOptions::separator`,
  and `FwWriterOptions::truncation` are gone — configure these on
  `FwWriterSchemaBuilder` instead.

### Migration

```rust
// Reader: before (0.1.x)
let mut reader = FwReader::builder(7)
    .field(FwReaderField::builder(0..5).build())
    .field(FwReaderField::builder(5..7).build())
    .separator(RecordSeparator::Lf)
    .from_reader(data)?;

// Reader: after (0.2.0)
let schema = FwReaderSchema::builder(7)
    .field(FwReaderField::builder(0..5).build())
    .field(FwReaderField::builder(5..7).build())
    .separator(RecordSeparator::Lf)
    .build()?;
let mut reader = FwReader::options(schema).from_reader(data);

// Writer: before (0.1.x)
let mut writer = FwWriter::builder()
    .field(FwWriterField::builder(5).build())
    .separator(RecordSeparator::Lf)
    .truncation(TruncationPolicy::Right)
    .from_writer(buf);

// Writer: after (0.2.0)
let schema = FwWriterSchema::builder()
    .field(FwWriterField::builder(5).build())
    .separator(RecordSeparator::Lf)
    .truncation(TruncationPolicy::Right)
    .build();
let mut writer = FwWriter::options(schema).from_writer(buf);
```

## [0.1.0] - Initial release
