Master the fundamental concepts of rust for systems programming through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksIndustrial C-to-Rust ports (Fish shell, Android components, DARPA TRACTOR research) succeed when idioms map cleanly. You are not transliterating syntax; you are replacing manual memory with ownership and errno checks with Result.
| C habit | Rust idiom |
|---|---|
malloc/free | Box, Vec, owned buffers |
char* | &str, String, CStr at FFI edges |
| NULL pointers | Option<T> |
union | enum with variants |
for (i=0; ...) | iterators |
cLoading…
rustLoading…
Start porting with behavior parity tests, then tighten types. Keep unsafe at FFI boundaries only.
For this exercise, you will port a small C utility to Rust and compare output and runtime. This task asks you to document each pattern swap, because migration reviews fail when teams copy pointers verbatim into *mut u8 without a safety story.
Keep the relevant man page, ABI doc, or Rust reference chapter open while you work. When your output disagrees with the reference implementation on the same machine, the mismatch is usually an alignment rule, an off-by-one terminator, or a register slot you misread in GDB. Skim the official documentation for the tool or ABI named in the exercise; the prose changes, but register roles, syscall numbers, and ownership rules stay stable across releases.
The C classic strrev swaps bytes from both ends. Port it to Rust and the compiler will not let you write it naively, because a String must always be valid UTF-8, and reversing the bytes of "é" (c3 a9) gives a9 c3, which is not UTF-8. For every input line, validate it as UTF-8, then show three reversals side by side: by chars, by words, and by bytes (the C way, which must be re-validated).
Any number of lines of text, each processed on its own (empty lines too). Two escapes let tests contain arbitrary bytes: \xHH (exactly two hex digits) is that byte, and \\ is one backslash. Any other backslash is literal.
std::str::from_utf8: no overlong forms, no surrogates (U+D800..U+DFFF), nothing above U+10FFFF, and no truncated sequences. On failure, report valid_up_to (the index of the first byte of the bad sequence).s.chars().rev()).For an invalid line: invalid UTF-8 at byte K (N bytes). Otherwise:
cLoading…
Strings print in double quotes, byte for byte, except that " and the backslash get a backslash in front, newline, tab and carriage return print as \n, \t and \r, and other ASCII control characters (below 0x20, and 0x7f) print as \u{HEX} in lowercase hex. Use byte / char when the count is 1.
Input:
cLoading…
Output:
cLoading…
read_to_end), not as a String, since some test lines are deliberately invalid.String::from_utf8 / str::from_utf8 and Utf8Error::valid_up_to rather than trusting the input.Hidden tests cover 4-byte emoji, a combining accent (char reversal moves it onto the wrong letter, which is why real text editors reverse grapheme clusters), control characters, empty lines, and invalid input (a stray continuation byte, a truncated sequence, an overlong encoding, a surrogate, a code point above U+10FFFF).