to-values 0.1.0

Flatten values into ordered f32 feature vectors.
# to-values

[![Crates.io](https://img.shields.io/crates/v/to-values.svg)](https://crates.io/crates/to-values)
[![Documentation](https://docs.rs/to-values/badge.svg)](https://docs.rs/to-values)
[![CI](https://github.com/gusahlg/to-values/actions/workflows/ci.yml/badge.svg)](https://github.com/gusahlg/to-values/actions/workflows/ci.yml)
[![License](https://img.shields.io/crates/l/to-values.svg)](LICENSE-APACHE)

`to-values` flattens Rust values into ordered `f32` feature vectors. It is a
small building block for preparing inputs to neural networks,
reinforcement-learning environments, and other numeric models.

## Quick start

The default `derive` feature converts a struct in declaration order. Exclude
identifiers or any other non-feature data with `#[input(skip)]`.

```rust
use to_values::ToInputVector;

#[derive(ToInputVector)]
struct Observation {
    position: [f32; 2],
    health: u16,
    #[input(skip)]
    entity_id: u64,
    has_key: bool,
}

let observation = Observation {
    position: [2.0, -0.5],
    health: 75,
    entity_id: 17,
    has_key: true,
};

assert_eq!(
    observation.to_input_vector(),
    vec![2.0, -0.5, 75.0, 1.0],
);
```

## Included implementations

`ToInputVector` is implemented for:

- `f32`, `f64`, all signed and unsigned integer primitives, and pointer-sized
  integers;
- `bool`, encoded as `0.0` or `1.0`;
- slices, arrays, `Vec<T>`, `Box<T>`, shared and mutable references, the unit
  type, and tuples up to twelve elements when their contents implement the
  trait.

Values are flattened in iteration or declaration order. `f64` and integer
implementations use Rust's `as f32` conversion; this can lose precision. Model
code that needs normalization, one-hot encoding, a missing-value indicator, or
any other domain-specific representation should implement the trait itself.

Strings, characters, pointers, `Option`, and `Result` deliberately do not have
blanket implementations. Their correct encoding is model-specific, and an
implicit encoding could silently change a model's input shape.

## Custom implementations

Implement `append_input_vector` to specify the representation and ordering of
a domain type. Overriding `input_vector_len` is optional, but lets
`to_input_vector` allocate its output once when the length is cheap to know.

```rust
use to_values::ToInputVector;

struct Velocity {
    x: f32,
    y: f32,
}

impl ToInputVector for Velocity {
    fn input_vector_len(&self) -> usize {
        2
    }

    fn append_input_vector(&self, output: &mut Vec<f32>) {
        self.x.append_input_vector(output);
        self.y.append_input_vector(output);
    }
}
```

## Features and platforms

| Feature | Default | Purpose |
| --- | --- | --- |
| `derive` | Yes | Re-exports `#[derive(ToInputVector)]` and supports `#[input(skip)]`. |
| `std` | Yes | Enables the standard-library build. |

The conversion API itself supports `no_std` environments with `alloc`:

```toml
[dependencies]
to-values = { version = "0.1", default-features = false }
```

Add `features = ["derive"]` when a `no_std` crate also wants the derive macro.
The macro is a compile-time dependency only.

## Versioning

This crate follows [Semantic Versioning](https://semver.org/). The supported
minimum Rust version is 1.85.

## License

Licensed under either of:

- [MIT License]LICENSE-MIT
- [Apache License, Version 2.0]LICENSE-APACHE