Repository: google/comprehensive-rust
File: src/slices-and-lifetimes/exercise.rs (Rust)

Code before:
            let (value, remainder) = remainder.split_at(4);
            // Unwrap error because `value` is definitely 4 bytes long.
            let value = i32::from_le_bytes(value.try_into().unwrap());
            (FieldValue::I32(value), remainder)
        }
    };
    Ok((
        Field {
            field_num,
            value: fieldvalue,
        },
        remainder,
    ))
}

// ANCHOR: parse_message
/// Parse a message in the given data, calling `field_callback` for each field in the message.
///
/// The entire input is consumed.
fn parse_message(
    mut data: &[u8],
    field_callback: impl Fn(Field) -> Result<(), Error>,
) -> Result<(), Error> {
    while !data.is_empty() {
        let parsed = parse_field(data)?;
        field_callback(parsed.0)?;
        data = parsed.1;
    }
    Ok(())
}
// ANCHOR_END: parse_message

// ANCHOR: main
fn main() {
    /// Handle a field in a Person message.
    fn person_field(field: Field) -> Result<(), Error> {
        match field.field_num {
            1 => println!("name: {}", field.value.as_string()?),
            2 => println!("id: {}", field.value.as_u64()?),
            3 => {
                println!("phone:");
                parse_message(field.value.as_bytes()?, phone_number_field)?;
            }
            _ => {} // skip everything else
        }
        Ok(())
    }

    /// Handle a field in a PhoneNumber message.
    fn phone_number_field(field: Field) -> Result<(), Error> {
        match field.field_num {

Review comment (suggestion):
I don't remember if I intended this, but I kind of like seeing callbacks used in an example. I think I used callbacks because I was thinking of a Go implementation I hacked on. Anyway, it's probably idiomatic to use traits instead of callbacks where possible, so I think this is a good change.

Code after:
        WireType::I32 => {
            if remainder.len() < 4usize {
                return Err(Error::UnexpectedEOF);
            }
            let (value, remainder) = remainder.split_at(4);
            // Unwrap error because `value` is definitely 4 bytes long.
            let value = i32::from_le_bytes(value.try_into().unwrap());
            (FieldValue::I32(value), remainder)
        }
    };
    Ok((
        Field {
            field_num,
            value: fieldvalue,
        },
        remainder,
    ))
}

// ANCHOR: parse_message
/// Parse a message in the given data, calling `field_callback` for each field in the message.
///
/// The entire input is consumed.
fn parse_message<'a, T: ProtoMessage<'a>>(mut data: &'a [u8]) -> Result<T, Error> {
    let mut result = T::default();
    while !data.is_empty() {
        let parsed = parse_field(data)?;
        result.add_field(parsed.0)?;
        data = parsed.1;
    }
    Ok(result)
}
// ANCHOR_END: parse_message

// ANCHOR: message_types
#[derive(Debug, Default)]
struct PhoneNumber<'a> {
    number: &'a str,
    type_: &'a str,
}

#[derive(Debug, Default)]
struct Person<'a> {
    name: &'a str,
    id: u64,
    phone: Vec<PhoneNumber<'a>>,
}
// ANCHOR_END: message_types

impl<'a> ProtoMessage<'a> for Person<'a> {
    fn add_field(&mut self, field: Field<'a>) -> Result<(), Error> {