mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-03-20 06:21:09 +02:00
Add more description of proto to the proto exercise (#2475)
This also moves the test cases into `main` so they are visible. Fixes #2466.
This commit is contained in:
parent
c61204ae18
commit
99c0948f4e
@ -29,15 +29,36 @@ message Person {
|
||||
}
|
||||
```
|
||||
|
||||
## Messages
|
||||
|
||||
A proto message is encoded as a series of fields, one after the next. Each is
|
||||
implemented as a "tag" followed by the value. The tag contains a field number
|
||||
(e.g., `2` for the `id` field of a `Person` message) and a wire type defining
|
||||
how the payload should be determined from the byte stream.
|
||||
how the payload should be determined from the byte stream. These are combined
|
||||
into a single integer, as decoded in `unpack_tag` below.
|
||||
|
||||
## Varint
|
||||
|
||||
Integers, including the tag, are represented with a variable-length encoding
|
||||
called VARINT. Luckily, `parse_varint` is defined for you below. The given code
|
||||
also defines callbacks to handle `Person` and `PhoneNumber` fields, and to parse
|
||||
a message into a series of calls to those callbacks.
|
||||
called VARINT. Luckily, `parse_varint` is defined for you below.
|
||||
|
||||
## Wire Types
|
||||
|
||||
Proto defines several wire types, only two of which are used in this exercise.
|
||||
|
||||
The `Varint` wire type contains a single varint, and is used to encode proto
|
||||
values of type `int32` such as `Person.id`.
|
||||
|
||||
The `Len` wire type contains a length expressed as a varint, followed by a
|
||||
payload of that number of bytes. This is used to encode proto values of type
|
||||
`string` such as `Person.name`. It is also used to encode proto values
|
||||
containing sub-messages such as `Person.phones`, where the payload contains an
|
||||
encoding of the sub-message.
|
||||
|
||||
## Exercise
|
||||
|
||||
The given code also defines callbacks to handle `Person` and `PhoneNumber`
|
||||
fields, and to parse a message into a series of calls to those callbacks.
|
||||
|
||||
What remains for you is to implement the `parse_field` function and the
|
||||
`ProtoMessage` trait for `Person` and `PhoneNumber`.
|
||||
|
@ -18,8 +18,8 @@
|
||||
enum WireType {
|
||||
/// The Varint WireType indicates the value is a single VARINT.
|
||||
Varint,
|
||||
/// The I64 WireType indicates that the value is precisely 8 bytes in
|
||||
/// little-endian order containing a 64-bit signed integer or double type.
|
||||
// The I64 WireType indicates that the value is precisely 8 bytes in
|
||||
// little-endian order containing a 64-bit signed integer or double type.
|
||||
//I64, -- not needed for this exercise
|
||||
/// The Len WireType indicates that the value is a length represented as a
|
||||
/// VARINT followed by exactly that number of bytes.
|
||||
@ -195,6 +195,34 @@ impl<'a> ProtoMessage<'a> for PhoneNumber<'a> {
|
||||
|
||||
// ANCHOR: main
|
||||
fn main() {
|
||||
let person_id: Person = parse_message(&[0x10, 0x2a]);
|
||||
assert_eq!(person_id, Person { name: "", id: 42, phone: vec![] });
|
||||
|
||||
let person_name: Person = parse_message(&[
|
||||
0x0a, 0x0e, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6c, 0x20,
|
||||
0x6e, 0x61, 0x6d, 0x65,
|
||||
]);
|
||||
assert_eq!(person_name, Person { name: "beautiful name", id: 0, phone: vec![] });
|
||||
|
||||
let person_name_id: Person =
|
||||
parse_message(&[0x0a, 0x04, 0x45, 0x76, 0x61, 0x6e, 0x10, 0x16]);
|
||||
assert_eq!(person_name_id, Person { name: "Evan", id: 22, phone: vec![] });
|
||||
|
||||
let phone: Person = parse_message(&[
|
||||
0x0a, 0x00, 0x10, 0x00, 0x1a, 0x16, 0x0a, 0x0e, 0x2b, 0x31, 0x32, 0x33,
|
||||
0x34, 0x2d, 0x37, 0x37, 0x37, 0x2d, 0x39, 0x30, 0x39, 0x30, 0x12, 0x04,
|
||||
0x68, 0x6f, 0x6d, 0x65,
|
||||
]);
|
||||
assert_eq!(
|
||||
phone,
|
||||
Person {
|
||||
name: "",
|
||||
id: 0,
|
||||
phone: vec![PhoneNumber { number: "+1234-777-9090", type_: "home" },],
|
||||
}
|
||||
);
|
||||
|
||||
// Put that all together into a single parse.
|
||||
let person: Person = parse_message(&[
|
||||
0x0a, 0x07, 0x6d, 0x61, 0x78, 0x77, 0x65, 0x6c, 0x6c, 0x10, 0x2a, 0x1a,
|
||||
0x16, 0x0a, 0x0e, 0x2b, 0x31, 0x32, 0x30, 0x32, 0x2d, 0x35, 0x35, 0x35,
|
||||
@ -203,53 +231,16 @@ fn main() {
|
||||
0x2d, 0x35, 0x33, 0x30, 0x38, 0x12, 0x06, 0x6d, 0x6f, 0x62, 0x69, 0x6c,
|
||||
0x65,
|
||||
]);
|
||||
println!("{:#?}", person);
|
||||
assert_eq!(
|
||||
person,
|
||||
Person {
|
||||
name: "maxwell",
|
||||
id: 42,
|
||||
phone: vec![
|
||||
PhoneNumber { number: "+1202-555-1212", type_: "home" },
|
||||
PhoneNumber { number: "+1800-867-5308", type_: "mobile" },
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
// ANCHOR_END: main
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_id() {
|
||||
let person_id: Person = parse_message(&[0x10, 0x2a]);
|
||||
assert_eq!(person_id, Person { name: "", id: 42, phone: vec![] });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_name() {
|
||||
let person_name: Person = parse_message(&[
|
||||
0x0a, 0x0e, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6c, 0x20,
|
||||
0x6e, 0x61, 0x6d, 0x65,
|
||||
]);
|
||||
assert_eq!(
|
||||
person_name,
|
||||
Person { name: "beautiful name", id: 0, phone: vec![] }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_just_person() {
|
||||
let person_name_id: Person =
|
||||
parse_message(&[0x0a, 0x04, 0x45, 0x76, 0x61, 0x6e, 0x10, 0x16]);
|
||||
assert_eq!(person_name_id, Person { name: "Evan", id: 22, phone: vec![] });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_phone() {
|
||||
let phone: Person = parse_message(&[
|
||||
0x0a, 0x00, 0x10, 0x00, 0x1a, 0x16, 0x0a, 0x0e, 0x2b, 0x31, 0x32, 0x33,
|
||||
0x34, 0x2d, 0x37, 0x37, 0x37, 0x2d, 0x39, 0x30, 0x39, 0x30, 0x12, 0x04,
|
||||
0x68, 0x6f, 0x6d, 0x65,
|
||||
]);
|
||||
assert_eq!(
|
||||
phone,
|
||||
Person {
|
||||
name: "",
|
||||
id: 0,
|
||||
phone: vec![PhoneNumber { number: "+1234-777-9090", type_: "home" },],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user