Armando Montanez | 179aa8e | 2021-03-10 11:46:35 -0800 | [diff] [blame] | 1 | .. _module-pw_snapshot-proto_format: |
| 2 | |
| 3 | ===================== |
| 4 | Snapshot Proto Format |
| 5 | ===================== |
| 6 | The Snapshot proto format depends on proto handling properties that directly |
| 7 | inform how the proto should be used. If two proto messages use field numbers |
| 8 | in a mutually exclusive manner, they can be encoded to the same buffer, and |
| 9 | decoded independently without any errors. An example is illustrated below: |
| 10 | |
| 11 | .. code-block:: |
| 12 | |
| 13 | // This message uses field numbers 1, 2, and 3. |
| 14 | message BasicLog { |
| 15 | string message = 1; |
| 16 | LogLevel level = 2; |
| 17 | int64 timestamp = 3; |
| 18 | } |
| 19 | |
| 20 | // This message uses field numbers 16 and 17, which are mutually exclusive |
| 21 | // to the numbers used in BasicLog. |
| 22 | message ExtendedLog { |
| 23 | string file_name = 16; |
| 24 | uint32 line_nubmer = 17; |
| 25 | } |
| 26 | |
| 27 | In the above example, a BasicLog and ExtendedLog can be encoded to the same |
| 28 | buffer and then be decoded without causing any problems. What breaks |
| 29 | this is when either of the two messages above are updated to use the same field |
| 30 | number for different types. This can be ameliorated by specifying reserved |
| 31 | field number ranges as shown below: |
| 32 | |
| 33 | .. code-block:: |
| 34 | |
| 35 | message BasicLog { |
| 36 | string message = 1; |
| 37 | LogLevel level = 2; |
| 38 | int64 timestamp = 3; |
| 39 | |
| 40 | // ExtendedLog uses these field numbers. These field numbers should never |
| 41 | // be used by BasicLog. |
| 42 | reserved 16 to max; |
| 43 | } |
| 44 | |
| 45 | message ExtendedLog { |
| 46 | // BasicLog uses these field numbers. These field numbers should never |
| 47 | // be used by ExtendedLog. |
| 48 | reserved 1 to 15; |
| 49 | |
| 50 | string file_name = 16; |
| 51 | uint32 line_nubmer = 17; |
| 52 | } |
| 53 | |
| 54 | This is exactly how the Snapshot proto is set up. While a SnapshotMetadata proto |
| 55 | message provides a good portion of the valuable snapshot contents, the larger |
| 56 | Snapshot message specifies field numbers and reserved field ranges to clarify |
| 57 | which field numbers are left to a project for declaring a mutually exclusive |
| 58 | project-specific proto message that can be used to augment the data natively |
| 59 | supported by the upstream proto. |
| 60 | |
| 61 | -------------------- |
| 62 | Module-Specific Data |
| 63 | -------------------- |
| 64 | Some upstream Pigweed modules provide a ``Snapshot*`` message that overlays the |
| 65 | main Snapshot message. These messages share a field number with the Snapshot |
| 66 | proto, which lets modules provide a helper that populates a subset of the |
| 67 | Snapshot proto without explicitly depending on the Snapshot proto. |
| 68 | |
| 69 | Example: |
| 70 | .. code-block:: |
| 71 | |
| 72 | // snapshot.proto |
| 73 | message Snapshot { |
| 74 | ... |
| 75 | // Information about allocated Thread. |
| 76 | repeated pw.thread.Thread threads = 18; |
| 77 | } |
| 78 | |
| 79 | // thread.proto |
| 80 | |
| 81 | // This message overlays the pw.snapshot.Snapshot proto. It's valid to encode |
| 82 | // this message to the same sink that a Snapshot proto is being written to. |
| 83 | message SnapshotThread { |
| 84 | // Thread information. |
| 85 | repeated pw.thread.Thread threads = 18; |
| 86 | } |
| 87 | |
| 88 | It is **critical** that the SnapshotThread message is in sync with the larger |
| 89 | Snapshot proto. If the type or field numbers are different, the proto decode |
| 90 | will fail. If the semantics are different, the decode will likely succeed but |
| 91 | might provide misleading information. |