Skip to content

Rust Target Overview

Genotype generates idiomatic Rust code that can be used directly in the application or published as a package.

This overview shows how Genotype types translate to Rust, target-specific features and configuration options.

See the Quick Genotype Language Tour for the language overview and Rust Configuration for detailed configuration reference.

The following examples give an overview of how Genotype translates into Rust.

This source combines an object, a literal field, an optional field, a record, and any:

Book: {
kind: "book",
displayTitle: string,
subtitle?: string,
ratings: { []: int },
extra: any,
}

The generated module includes its type definitions and imports:

use std::collections::BTreeMap;
use genotype_runtime::Any;
use litty::serde_literals;
use serde::{Deserialize, Serialize};
#[serde_literals]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[literals(kind = "book")]
pub struct Book {
#[serde(rename = "displayTitle")]
pub display_title: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subtitle: Option<String>,
pub ratings: BTreeMap<String, i64>,
pub extra: Any,
}

Genotype unions translate into Rust enums. Non-literal unions use untagged serialization to preserve the original data shape.

Value: string | int
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Value {
String(String),
Int(i64),
}

Genotype number translates into the Rust f64 type.

Amount: number
pub type Amount = f64;

Genotype int translates into the Rust i64 type.

Count: int
pub type Count = i64;

Genotype float translates into the Rust f64 type.

Ratio: float
pub type Ratio = f64;

Sized Genotype numeric types translate directly to their Rust counterparts.

SmallCount: i16
PreciseRatio: f32
LargeCount: i128
pub type SmallCount = i16;
pub type PreciseRatio = f32;
pub type LargeCount = i128;

Genotype boolean translates into the Rust bool type.

Ready: boolean
pub type Ready = bool;

Genotype string translates into the Rust owned String type.

Title: string
pub type Title = String;

Genotype literal types translate into named Rust structs with attributes that preserve the exact serialized value.

Category: "fiction"
#[serde_literal("fiction")]
#[derive(Serialize, Deserialize)]
pub struct Category;

Genotype null translates into a Rust type that serializes as null.

Empty: null
#[serde_literal(null)]
#[derive(Serialize, Deserialize)]
pub struct Empty;

Genotype branded primitives translate into Rust newtype structs, distinct from their underlying primitive.

BookId: @string
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BookId(pub String);

Genotype objects translate into public Rust structs with Serde support. Nested objects become separate named structs.

Book: { title: string }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Book {
pub title: String,
}

Optional Genotype object fields translate into Rust Option<T> fields. Absent values are omitted during serialization.

Draft: { subtitle?: string }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Draft {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subtitle: Option<String>,
}

Genotype object extensions translate into Rust structs containing the base struct’s fields.

Named: { name: string }
NamedBook: { ...Named, pages: int }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Named {
pub name: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct NamedBook {
pub name: String,
pub pages: i64,
}

Genotype arrays translate into Rust Vec<T> types.

Titles: [string]
pub type Titles = Vec<String>;

Genotype tuples translate directly to Rust tuple types.

Point: (float, float)
pub type Point = (f64, f64);

Genotype records translate into Rust BTreeMap<K, V> types. An omitted key type means string keys.

Scores: { []: int }
pub type Scores = BTreeMap<String, i64>;

Genotype any translates into the Genotype runtime’s Any type.

Payload: any
pub type Payload = Any;

Genotype generic types translate into Rust generic types.

Envelope<Body>: { body: Body }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Envelope<Body> {
pub body: Body,
}

Genotype recursive types translate into Rust types with Box indirection where needed to give them a finite size.

LinkedNode: { value: string, next?: LinkedNode }
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LinkedNode {
pub value: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next: Option<Box<LinkedNode>>,
}

Annotations let you customize enum variants directly in Genotype:

Status:
| #[variant = "Available"] "in_stock"
| "sold_out"

Here variant names the Rust variant Available. Its serialized value remains "in_stock".

Use [rs] in genotype.toml to configure Rust. See the Rust Configuration Reference for more details.

See Genotype Configuration for global settings and Common Target Options.