A human-friendly DSL for ATProto Lexicons forked from stavola.xyz/mlf
2.3 kB · 59 lines
Markdown
at main

+++ title = "Rust" description = "Rust code generator" weight = 3 +++

The mlf-codegen-rust generator emits Rust structs from MLF lexicons, with serde derives for round-trip JSON support.

Usage #

[[output]]
type = "rust"
directory = "./crates/lex-types/src/generated"
mlf generate code -g rust

This is the generator the MLF project itself uses for its mlf-generated-lexicon crate — see the lol.mlf.package lexicon and the corresponding generated struct for a live example.

Type mapping #

MLF type Rust
null serde_json::Value
boolean bool
integer i64
string String
bytes Vec<u8>
blob Vec<u8>
Datetime String (ISO 8601)
Did, AtUri, Cid, Handle, Nsid, Tid, RecordKey, Uri, Language, AtIdentifier String
T[] (array) Vec<T>
T | U (union) #[serde(untagged)] enum
{ …fields… } (object) named struct
Custom def type Foo pub struct Foo { … }
record foo pub struct Foo { … } (outer collection is the file's NSID)

Field syntax #

  • field: T → pub field: Option<T> with #[serde(skip_serializing_if = "Option::is_none")]
  • field!: T → pub field: T (required)

Field names are snake_cased (Rust convention); a #[serde(rename = "…")] attribute preserves the original camelCase for on-wire fidelity.

Derives #

Generated structs carry #[derive(Debug, Clone, Serialize, Deserialize)]. Nothing else — no PartialEq, no Eq, no Hash. If you need those, wrap or extend the generated types in a sibling module.

Doc comments #

/// doc comments on defs and fields are preserved as /// Rust doc comments. They show up in rustdoc + LSP hover + IDE completion.

What isn't covered yet #

  • Validators. No generated Validate trait impls. Use mlf-validation's RecordValidator if you need runtime validation against the lexicon.
  • Enum types. token declarations emit as a string newtype with known-value constants; no #[non_exhaustive] enum yet.