api_models.rs in Rust
A complete model set for an API payload: parse, validate, summarize.
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Payload {
lang: String,
#[serde(default)]
generated: bool,
tours: Vec<Tour>,
}
#[derive(Debug, Serialize, Deserialize)]
struct Tour {
slug: String,
title: String,
sections: Vec<Section>,
}
#[derive(Debug, Serialize, Deserialize)]
struct Section {
title: String,
steps: Vec<Step>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
enum Step {
Snippet { file: String, lines: u32 },
Script { file: String, lines: u32 },
}
impl Step {
fn file(&self) -> &str {
match self {
Step::Snippet { file, .. } | Step::Script { file, .. } => file,
}
}
fn lines(&self) -> u32 {
match self {
Step::Snippet { lines, .. } | Step::Script { lines, .. } => *lines,
}
}
}
fn summarize(payload: &Payload) -> BTreeMap<&str, u32> {
let mut totals = BTreeMap::new();
for tour in &payload.tours {
let steps: u32 =
tour.sections.iter().map(|s| s.steps.len() as u32).sum();
totals.insert(tour.slug.as_str(), steps);
}
totals
}
fn main() -> Result<(), serde_json::Error> {
let raw = r#"{
"lang": "rust",
"tours": [{
"slug": "traits",
"title": "Traits & generics",
"sections": [{
"title": "Trait objects",
"steps": [
{"kind": "snippet", "file": "rs_trait_objects.rs", "lines": 38},
{"kind": "script", "file": "shapes.rs", "lines": 96}
]
}]
}]
}"#;
let payload: Payload = serde_json::from_str(raw)?;
println!("{} generated={}", payload.lang, payload.generated);
println!("{:?}", summarize(&payload));
let longest = payload
.tours
.iter()
.flat_map(|t| &t.sections)
.flat_map(|s| &s.steps)
.max_by_key(|step| step.lines());
if let Some(step) = longest {
println!("longest: {} at {} lines", step.file(), step.lines());
}
println!("{}", serde_json::to_string(&payload)?.len());
Ok(())
}
How it works
- The models mirror the JSON with renames and defaults.
- A tagged enum covers the two kinds of step.
- The summary walks the parsed tree, not the raw text.
Keywords and builtins used here
BTreeMapOkPayloadResultSectionSomeStepStringTourVecasboolenumfilefnforifimplinletlinesmainmatchmutselfstrstructsummarizeu32use
The run, in numbers
- Lines
- 89
- Characters to type
- 1855
- Tokens
- 465
- Three-star pace
- 115 tpm
At the three-star pace of 115 tokens a minute, this run takes about 243 seconds.
Step 1 of 1 in Encore, step 11 of 11 in Serde & JSON.