We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Shape Your Data: Structs, Enums, Pattern Matching step 23 of 26
Decode bytes into enum variants
Repair Lvl::from_u8 so it recognizes the protocol's five log levels and rejects every other byte. Keep the enum and public function signature:
pub fn decode_levels(codes: Vec<u8>) -> Vec<String>
| Byte | Output |
|---|---|
| 10 | "Trace=10" |
| 20 | "Debug=20" |
| 30 | "Info=30" |
| 31 | "Warn=31" |
| 50 | "Error=50" |
| Any other value from 0 through 255 | "?={code}", using decimal digits without padding |
Preserve input order and duplicates. Empty input returns an empty vector.
For example, [10, 31, 40, 31] produces
["Trace=10", "Warn=31", "?=40", "Warn=31"].
Test inputs represent bytes as JSON integers from 0 through 255.
A discriminant identifies a variant
Lvl declares Trace = 10, Debug = 20, Info = 30, Warn without an explicit value, and Error = 50. An implicit discriminant is the previous variant's value plus one, so Warn is 31. If the first variant has no explicit value, its discriminant starts at zero. Duplicate values are rejected with E0081.
For this unit-only enum, #[repr(u8)] fixes the representation to u8.
It does not make every byte a valid Lvl. Only the declared variants are valid.
Lvl::Info can be cast to u8 to obtain 30, but u8 cannot be cast back to Lvl.
This complete, smaller example shows explicit and implicit values:
#[repr(u8)]
enum Status { Ready = 7, Busy, Done }
fn main() {
assert_eq!(Status::Ready as u8, 7);
assert_eq!(Status::Busy as u8, 8);
assert_eq!(Status::Done as u8, 9);
}
Representation and enum-to-integer casting have additional rules for other enum shapes. See the enum reference.
Decode with a fallible conversion
The starter's Some(code as Self) fails with E0605. A numeric cast does not
validate the input against the enum's variants. Implement from_u8 as a match
returning Some of the corresponding variant for each recognized byte and
None for every other byte. Keep the default arm; unknown protocol values
should be reported, not treated as a valid level or made to panic.
The supplied decode_levels function already formats Some and None correctly. Its Debug formatting uses the variant names, and its enum-to-u8 cast reports the discriminant. You only need to repair the conversion method.
Rust has no built-in derive that generates this reverse mapping. External procedural macros can provide conversions in other projects; this exercise uses an explicit match and the standard library. A separate API could instead implement TryFrom<u8> with an error type, but keep Option<Self> here.
Compare variants without comparing payloads
An enum with payload fields cannot be converted to an integer with this numeric cast. To compare which variant is present while ignoring its data, use mem::discriminant. This complete example compares variants and separately reads the payload:
use std::mem::discriminant;
enum Message { Number(u8), End }
fn main() {
let first = Message::Number(1);
let second = Message::Number(9);
assert_eq!(discriminant(&first), discriminant(&second));
assert_ne!(discriminant(&first), discriminant(&Message::End));
if let Message::Number(value) = first {
assert_eq!(value, 1);
}
}
The returned Discriminant value is an opaque token for variant comparison, not a numeric protocol code. Use the explicit decoder for incoming bytes and the defined Lvl cast for outgoing codes.
Passing requires the exact output strings, successful compilation and Clippy with warnings treated as errors.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.