Inndata (.proto-skjema)

Utdata (Rust)

Hva dette verktøyet gjør

Du har et Protocol Buffers-skjema og en Rust-tjeneste eller -klient som må snakke med det. Standardveien er prost (eller tonic for gRPC) hektet inn i et build.rs-skript — solid, men overkill når du bare vil skissere typene og sjekke formene mot koden din. Denne konvertereren gjør skjemaet om til struct-definisjoner i nettleseren din. Lim inn, kopier, slipp ned i src/types.rs, kjør videre.

Utdataen bruker #[derive(Debug, Default, Clone, Serialize, Deserialize)] på hver struct slik at den round-tripper via JSON med serde, og #[repr(i32)]-enumer der null-verdivarianten er merket #[default] slik at Default::default() matcher proto3-semantikken. Singulære nestede meldinger blir Option<T> — Rust krever eksplisitt nullbarhet, og det matcher det prost genererer. Vec<T> for repeated-felt og HashMap<K, V> for maps får begge #[serde(default)], slik at felter som mangler deserialiseres til tomme containere i stedet for å feile.

Type-mappingen følger proto3 JSON-mapping-spesifikasjonen: string/bytesString/Vec<u8>, de ulike størrelses-heltallene mapper til i32/i64/u32/u64, og floats lander på f32/f64. Feltnavn konverteres til snake_case (det er allerede Rust-konvensjonen, så de fleste felter går gjennom uendret), og enum-varianter mister det skrikende SCREAMING_SNAKE-prefikset — ORDER_STATUS_UNSPECIFIED i enumen OrderStatus blir til Unspecified, akkurat som du ville skrevet det for hånd. Konverteringen kjører helt klient-side; ingenting fra skjemaet ditt forlater siden.

Slik bruker du det

Tre steg. Utdataen er klar til å limes inn i en hvilken som helst Rust-crate som har serde i avhengighetene.

1

Lim inn .proto-skjemaet ditt

Slipp skjemaet i editoren til venstre. syntax = "proto3"; øverst er valgfritt — parseren håndterer nestede message-blokker, enum-deklarasjoner, oneof, map<K, V> og feltopsjoner. Imports gjenkjennes, men hoppes over, så lim inn importerte typer inline om du er avhengig av dem.

Feltnavn følger Rust-konvensjonene automatisk: order_id blir værende order_id, shippingAddress (om du har camelCase i skjemaet) blir shipping_address. Struct- og enum-navn beholder PascalCase.

2

Les utdataen

Til høyre: en flat liste av pub struct- og pub enum-deklarasjoner. Enumer kommer først, deretter meldinger i deklarasjonsrekkefølge, med nestede typer foran foreldrene sine. Linjen use serde::{Deserialize, Serialize}; er alltid der; use std::collections::HashMap; dukker bare opp om skjemaet ditt har map-felter.

3

Slipp inn i craten din

Lim inn utdataen i en modulfil. Så lenge du har serde = { version = "1", features = ["derive"] } og serde_json i Cargo.toml-en din, kompilerer det. Derfra er det vanlig Rust — kobl det inn i en reqwest-klient, en Cloudflare Worker, en axum-handler, hvor enn du trenger typet tilgang til meldingsdataen.

Når det faktisk sparer tid

Skissere typer for en ny Rust-tjeneste

Du bygger en Rust-tjeneste som konsumerer et gRPC-gateway-endepunkt, men du vil ikke sette opp en full build.rs med prost ennå. Lim inn .proto-en, slipp structene i types.rs, JSON-decode svaret, send ut prototypen.

Reviewe en Protobuf API-endring

En backend-kollega har lagt til felter i en melding. Du vil se hvordan Rust-formen endrer seg uten å bygge hele craten på nytt. Lim inn det nye .proto-et, diff utdataen mot de eksisterende typene dine, legg igjen en fokusert review-kommentar.

Krysssjekke prost-generert kode

Bygget ditt bruker prost med egne type_attribute-regler, og du vil ha en ren referanse på hvordan de uendrede typene ser ut. Lim inn skjemaet her for en side-om-side. Nyttig når du planlegger attributtendringer eller migrerer til en annen codegen-pipeline.

CLI-verktøy og engangsskripter

Du skriver en liten Rust-CLI som kaller et JSON-API som er bygget på Protobuf. Å koble inn prost bare for et 100-linjers verktøy er mer seremoni enn jobben krever. Plukk structene herfra, deriv serde, send ut binæren.

Vanlige spørsmål

Sendes skjemaet mitt noe sted?

Nei. Både parseren og Rust-emitteren kjører som JavaScript i nettleseren din. Åpne DevTools, følg med på Network-fanen mens du limer inn — null requests. Nyttig når skjemaet inneholder interne typenavn, pakke-paths eller noe annet du ikke ville sendt til en tredjepartstjeneste.

Hvorfor er nestede meldinger pakket inn i Option?

Rust har ikke nullbare referanser som Java eller Go — enten er verdien til stede, eller så bruker du Option<T> for å gjøre fraværet eksplisitt. Singulære submessages i proto3 er nullbare på tråden (felt-taggen kan mangle helt), så den idiomatiske Rust-formen er Option<Address>, ikke Address. Det matcher det prost genererer. Skalarer og enumer pakkes ikke inn fordi nullverdiene deres (tom streng, 0, false, #[default]-enum-varianten) er gyldige Rust-verdier.

Hvorfor er 64-bits ints typed som i64/u64 i stedet for strings?

I Rust er det ingen presisjonsbekymring — i64 og u64 er førsteklassestyper, ulikt JavaScript der 64-bits verdier er strings. Hvis du deserialiserer JSON produsert av en streng proto3 JSON-encoder, kommer verdiene inn som strings; serde konverterer ikke automatisk. Legg #[serde(with = "serde_with::DisplayFromStr")] eller en egen deserializer på de feltene om du treffer det tilfellet.

Hvorfor HashMap i stedet for BTreeMap?

HashMap matcher det prost emitterer for map<K, V>-felt og er den rette defaulten — proto-map-felt er uordnede. Trenger du stabil iterasjonsrekkefølge, bytter du typen for hånd til BTreeMap; resten av koden trenger ikke å endres.

Skal jeg bruke denne utdataen med prost eller tonic?

Dette er rett og slett serde-deriverte structer, ikke prost-encodede. De round-tripper via proto3 JSON med serde_json, men encoder/decoder ikke det binære wire-formatet. Trenger du binær protobuf-encoding, kjør prost via et build.rs-steg. Trenger du gRPC, bruk tonic. Denne konvertereren er for JSON-over-HTTP-tilfellet (gRPC-gateway, Connect, JSON-transkoding).

Håndterer den oneof?

Hvert felt i en oneof emitteres som et vanlig struct-felt. Utdataen håndhever ikke "nøyaktig én"-betingelsen som oneof impliserer — for det måtte du brukt en Rust-enum med en variant per case, og det avhenger av runtime-semantikken din. Trenger du streng oneof-håndtering, redigerer du utdataen for hånd til en pub enum.

Relaterte verktøy

Hvis du jobber med Protobuf, JSON og Rust, passer disse godt sammen: