Deliberate practice

Six labs that force the right skills to surface.

Every lab starts with retrieval, then moves through a worked example, a faded build, malformed-input tests, and one feedback metric.

Lab Protocol

Do not read first. Try, fail visibly, then read the exact resource that explains the failure.

01
Recall
02
Implement
03
Attack with bad input
04
Explain invariant
90 minRust ownership, slices, parsing without accidental allocation.

Lab 1 - Fixed-width ASCII from slices

Parse symbol, price, and size from a byte row into borrowed/numeric fields.

Retrieval first

Before coding: write the lifetime relationship between input bytes and parsed symbol.

Worked example

Given b"MSFT 00018425000100", split offsets first, then parse each field with explicit error variants.

Feedback metric

Pass all malformed-input tests before reading more packet docs.

Build
  • Define ParsedQuote with symbol: &str, price: u64, size: u32.
  • Reject rows shorter than the full fixed-width layout.
  • Use std::str::from_utf8 and decimal parsing only after slicing bounds are checked.
Tests
  • Happy path parses symbol, price, and size.
  • Short row returns an error, never panics.
  • Non-UTF8 symbol returns an error.
  • Non-digit price returns an error.
The Rust Programming LanguageRustlingsRust Book testing chapter
2 hrFile format discipline, endian handling, checked offsets.

Lab 2 - PCAP record walker

Iterator over captured packet bytes from a classic PCAP savefile.

Retrieval first

From memory: name global header fields that affect byte order and link type.

Worked example

Read magic first, select endian, parse packet header, then trust incl_len only after comparing with remaining bytes.

Feedback metric

If any test uses unwrap in parser code, redo error design.

Build
  • Parse PCAP global header and reject unsupported magic values.
  • Parse packet records one at a time through BufReader.
  • Return borrowed packet slices if file is buffered in memory, or owned Vec<u8> if streaming from disk.
Tests
  • Little-endian sample emits one packet.
  • Truncated global header is rejected.
  • Record with incl_len beyond file length is rejected.
  • Unsupported link type is rejected with a clear message.
pcap-savefile(5)Wireshark libpcap file format notesbyteorder
2 hrNetwork layers, byte order, protocol filtering.

Lab 3 - Ethernet / IPv4 / UDP payload

Function that accepts an Ethernet frame and returns UDP payload plus source/destination ports.

Retrieval first

Sketch the offsets, then explain why IPv4 IHL changes the UDP start offset.

Worked example

Ethernet type 0x0800 -> IPv4 protocol 17 -> UDP length field -> payload range.

Feedback metric

Run tests with one-byte truncation at every header boundary.

Build
  • Reject non-IPv4 Ethernet frames.
  • Honor IPv4 IHL instead of assuming 20 bytes.
  • Reject fragmented IPv4 packets unless the sample spec says otherwise.
  • Validate UDP length against available bytes before slicing payload.
Tests
  • Valid IPv4 UDP frame extracts payload.
  • TCP frame is skipped or rejected according to caller contract.
  • IPv4 header with IHL > 5 still locates UDP correctly.
  • UDP length shorter than header is rejected.
RFC 791: IPv4RFC 768: UDPBeej's Guide to Network Concepts
90 minMarket-data semantics and typed parsing.

Lab 4 - Quote message parser

Parse Tsuru quote payload into timestamped quote events.

Retrieval first

Separate transport timestamp, exchange timestamp, symbol, bid/ask, price, and size.

Worked example

Convert fixed-width or binary fields into typed values first; only format for stdout at the final boundary.

Feedback metric

You can explain each field to someone who has never seen market data.

Build
  • Represent side as an enum rather than a bool.
  • Represent price as integer ticks or fixed decimal, not f64.
  • Preserve sequence/timestamp fields needed by reorder logic.
Tests
  • Known payload renders exact expected quote line.
  • Unknown side is rejected.
  • Invalid price precision is rejected.
  • Parser and renderer are tested separately.
Tsuru code sampleNasdaq TotalView-ITCH 5.0 specTrading and Exchanges, Larry Harris
2 hrStreaming algorithms, heap invariants, bounded memory.

Lab 5 - Bounded 3-second reorder

Reorder stream by timestamp while keeping only the allowed delay window.

Retrieval first

State: item is safe to emit when max_seen_timestamp - item.timestamp >= 3 seconds.

Worked example

Push every event into a min-heap; after each push, pop all events now safe. At EOF, drain heap.

Feedback metric

Memory use should scale with window size, not file size.

Build
  • Wrap BinaryHeap ordering so smallest timestamp pops first.
  • Track max timestamp observed so far.
  • Emit safe events incrementally; never collect the full stream.
Tests
  • In-order input passes through.
  • Out-of-order events within 3 seconds are fixed.
  • Events beyond the window preserve bounded behavior defined by the sample.
  • EOF drains remaining heap in timestamp order.
BinaryHeapMIT 6.006 heap lectureOpenDSA external sorting
2 hrBenchmarking, profiling, allocation pressure.

Lab 6 - Profile after correctness

One benchmark report and one measured improvement patch.

Retrieval first

Before optimizing: name the suspected hotspot and how you will falsify it.

Worked example

Benchmark parse_udp_payload on 10k frames, capture flamegraph, then remove one measured allocation.

Feedback metric

Claim no speedup without a metric, workload, and baseline.

Build
  • Add Criterion benchmark for parser throughput.
  • Run flamegraph or equivalent profiler on release build.
  • Change only one hot path and rerun benchmark.
Tests
  • Functional tests still pass.
  • Benchmark command is documented.
  • Before/after numbers are recorded.
  • Optimization rationale names the profiler evidence.
The Rust Performance BookCriterion.rscargo-flamegraphperf wiki