# parquet.stats

> A module of parquet's API.

Column statistics, decoded from their raw bytes to typed values.

`Statistics.min_value` / `max_value` are the *physical* bytes of a value — four
little-endian bytes for an `INT32` column, the raw string for a `BYTE_ARRAY`
one — so every consumer has to decode them against the column's physical type.
`TypedStats` does that once and hands back `Int64`, `Float64`, `String` or raw
bytes, which is what `iceberg.mojo` wants for `lower_bounds` / `upper_bounds`.

The deprecated `min` / `max` fields are used only when `min_value` /
`max_value` are absent, and only for types whose old sort order was already
correct (everything except signed comparisons of `BYTE_ARRAY`, where
parquet-mr's historical order was wrong — such a column reports no bounds
rather than a wrong one).

## Structs

### `ScalarValue`

```mojo
struct ScalarValue
```

One decoded statistic, or one predicate literal.

Implements: `Copyable`, `Defaultable`, `Movable`, `Writable`

Fields:

- `kind: Int`
- `i: Int64`
- `u: UInt64`
- `f: Float64`
- `b: List[UInt8]`

#### `__init__`

```mojo
def __init__(out self)
```

#### `of_int`

```mojo
def of_int(v: Int64) -> Self
```

#### `of_uint`

```mojo
def of_uint(v: UInt64) -> Self
```

#### `of_float`

```mojo
def of_float(v: Float64) -> Self
```

#### `of_bool`

```mojo
def of_bool(v: Bool) -> Self
```

#### `of_bytes`

```mojo
def of_bytes(data: Span[UInt8]) -> Self
```

#### `of_string`

```mojo
def of_string(text: StringSpan) -> Self
```

#### `as_string`

```mojo
def as_string(self) -> String
```

#### `write_to`

```mojo
def write_to(self, mut writer: T)
```

### `TypedStats`

```mojo
struct TypedStats
```

One column chunk's statistics, decoded.

Implements: `Copyable`, `Defaultable`, `Movable`

Fields:

- `has_min_max: Bool`
- `min: ScalarValue`
- `max: ScalarValue`
- `has_null_count: Bool`
- `null_count: Int64`
- `has_distinct_count: Bool`
- `distinct_count: Int64`

#### `__init__`

```mojo
def __init__(out self)
```

## Functions

### `compare_bytes`

```mojo
def compare_bytes(a: Span[UInt8], b: Span[UInt8]) -> Int
```

### `compare_scalars`

```mojo
def compare_scalars(a: ScalarValue, b: ScalarValue) -> Int
```

Order two scalars of the same kind. Raises on a kind mismatch.

### `decode_statistic`

```mojo
def decode_statistic(leaf: LeafColumn, raw: Span[UInt8]) -> ScalarValue
```

Decode one raw statistic against the leaf's physical and Arrow types.

### `decode_stats`

```mojo
def decode_stats(leaf: LeafColumn, st: Statistics) -> TypedStats
```

Decode a `Statistics` struct against one leaf column.

## Aliases

### `SV_NONE`

```mojo
comptime SV_NONE = 0
```

### `SV_INT`

```mojo
comptime SV_INT = 1
```

### `SV_UINT`

```mojo
comptime SV_UINT = 2
```

### `SV_FLOAT`

```mojo
comptime SV_FLOAT = 3
```

### `SV_BYTES`

```mojo
comptime SV_BYTES = 4
```

### `SV_BOOL`

```mojo
comptime SV_BOOL = 5
```
