# avro.resolve

> A module of avro's API.

Schema resolution — reading data written with one schema as another.

`resolve(writer, reader)` walks the two schemas once and builds a *plan*: a
flat list of `ResolveNode`s that says, for every position in the writer's
data, what to decode and where it lands in the reader's shape. Decoding then
follows the plan, so the per-record cost has no name lookups in it.

Supported (the common cases from the Avro spec's "Schema Resolution"):

- field reordering, and writer fields the reader dropped (skipped in place);
- reader fields the writer never wrote, filled from the field's `default`;
- numeric promotions `int → long → float → double`;
- `string ↔ bytes`;
- union member selection in both directions, plus a non-union writer read
  into a reader union;
- enum symbols missing from the reader, falling back to the reader enum's
  own `default`;
- records/enums/fixed matched by unqualified name, and by the reader's
  `aliases`.

## Structs

### `ResolveNode`

```mojo
struct ResolveNode
```

Implements: `Copyable`, `Movable`

Fields:

- `action: Int`
- `w: Int`: Writer schema node index.
- `r: Int`: Reader schema node index (-1 for a skip).
- `kids: List[Int]`: Child plan indices: array items, map values, union branches.
- `field_plan: List[Int]`: Per writer field: the child plan index, or -1 to skip the field.
- `field_slot: List[Int]`: Per writer field: the reader field position, or -1 to skip.
- `default_slots: List[Int]`: Reader field positions filled from the field's `default`.
- `default_values: List[Value]`
- `enum_map: List[Int]`: Per writer symbol: the reader symbol index, or -1 for the fallback.
- `enum_fallback: Int`
- `branch: Int`: Chosen reader union branch for RA_UNION_READER.
- `message: String`: Why RA_ERROR was planted.

#### `of`

```mojo
def of(action: Int, w: Int, r: Int) -> Self
```

### `ResolvedReader`

```mojo
struct ResolvedReader
```

A decoding plan produced by `resolve`.

Implements: `Copyable`, `Movable`

Fields:

- `writer: Schema`
- `reader: Schema`
- `plan: List[ResolveNode]`
- `root: Int`

#### `__init__`

```mojo
def __init__(out self, var writer: Schema, var reader: Schema)
```

#### `read_value`

```mojo
def read_value(self, mut d: Decoder) -> Value
```

Decode one datum written with `writer`, shaped as `reader`.

## Functions

### `resolve`

```mojo
def resolve(writer: Schema, reader: Schema) -> ResolvedReader
```

Build a decoding plan that reads `writer` data as `reader`.

### `default_value`

```mojo
def default_value(schema: Schema, i: Int, default_json: StringSpan) -> Value
```

Decode a field's JSON `default` into a `Value` shaped by `schema`.

## Aliases

### `RA_DIRECT`

```mojo
comptime RA_DIRECT = Int(0)
```

Kinds match exactly — decode with the writer schema.

### `RA_PROMOTE`

```mojo
comptime RA_PROMOTE = Int(1)
```

### `RA_RECORD`

```mojo
comptime RA_RECORD = Int(2)
```

### `RA_ENUM`

```mojo
comptime RA_ENUM = Int(3)
```

### `RA_ARRAY`

```mojo
comptime RA_ARRAY = Int(4)
```

### `RA_MAP`

```mojo
comptime RA_MAP = Int(5)
```

### `RA_UNION_WRITER`

```mojo
comptime RA_UNION_WRITER = Int(6)
```

### `RA_UNION_READER`

```mojo
comptime RA_UNION_READER = Int(7)
```

### `RA_SKIP`

```mojo
comptime RA_SKIP = Int(8)
```

### `RA_ERROR`

```mojo
comptime RA_ERROR = Int(9)
```

A writer union branch the reader cannot accept — only fatal if it is actually the branch on the wire.
