diff options
author | David Duarte <licorne@google.com> | 2024-06-04 00:34:17 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2024-06-04 00:34:17 +0000 |
commit | ae290114b002638ec5694cc0df5abf314c0e6681 (patch) | |
tree | ece4849b52cc8838865430cd1b93cc03cdbe3c8e | |
parent | ffc075afa2d15884a37b929cd35f1615462b046f (diff) | |
parent | 67a386da6a4243f5adf1733bf4c6679169f9d740 (diff) | |
download | pdl-runtime-main.tar.gz |
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pdl-runtime/+/3108708
Change-Id: Id1e82d2a2ab5a754ce8a8a8b79e4db2834dae5bf
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/lib.rs | 104 |
7 files changed, 102 insertions, 20 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index c80110d..d308c05 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "1aca6665980cddba4f12c36b13080694f1d76b4d" + "sha1": "4dbe66da6a922c64436a8f3a00a4ab1f0ebafbb6" }, "path_in_vcs": "pdl-runtime" }
\ No newline at end of file @@ -8,7 +8,7 @@ rust_library { host_supported: true, crate_name: "pdl_runtime", cargo_env_compat: true, - cargo_pkg_version: "0.2.3", + cargo_pkg_version: "0.3.0", crate_root: "src/lib.rs", edition: "2021", rustlibs: [ @@ -12,7 +12,7 @@ [package] edition = "2021" name = "pdl-runtime" -version = "0.2.3" +version = "0.3.0" authors = [ "Henri Chataing <henrichataing@google.com>", "David de Jesus Duarte <licorne@google.com>", diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 986c1c2..e1d300f 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "pdl-runtime" -version = "0.2.3" +version = "0.3.0" edition = "2021" description = "PDL's runtime library" repository = "https://github.com/google/pdl/" @@ -8,13 +8,13 @@ third_party { license_type: NOTICE last_upgrade_date { year: 2024 - month: 2 - day: 5 + month: 5 + day: 29 } identifier { type: "crates.io" - value: "https://static.crates.io/crates/pdl-runtime/pdl-runtime-0.2.3.crate" - version: "0.2.2" + value: "https://static.crates.io/crates/pdl-runtime/pdl-runtime-0.3.0.crate" + version: "0.3.0" } identifier { type: "Archive" @@ -45,5 +45,5 @@ Language specific instructions are provided for all supported backends: ## Similar projects - [Kaitai](https://kaitai.io) -- [EMBOSS](https://github.com/kimrutherford/EMBOSS) +- [Emboss](https://github.com/google/emboss) - [P4](https://p4.org/p4-spec/docs/P4-16-v1.0.0-spec.html) @@ -14,32 +14,114 @@ //! Helper definitions used used by the generated Rust backend. -use bytes::Bytes; -use thiserror::Error; +use bytes::{BufMut, Bytes, BytesMut}; /// Type of parsing errors. -#[derive(Debug, Error, PartialEq, Eq)] -pub enum Error { - #[error("Packet parsing failed")] +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum DecodeError { + #[error("packet parsing failed")] InvalidPacketError, #[error("{field} was {value:x}, which is not known")] - ConstraintOutOfBounds { field: String, value: u64 }, + ConstraintOutOfBounds { field: &'static str, value: u64 }, #[error("Got {actual:x}, expected {expected:x}")] InvalidFixedValue { expected: u64, actual: u64 }, #[error("when parsing {obj} needed length of {wanted} but got {got}")] - InvalidLengthError { obj: String, wanted: usize, got: usize }, + InvalidLengthError { obj: &'static str, wanted: usize, got: usize }, #[error("array size ({array} bytes) is not a multiple of the element size ({element} bytes)")] InvalidArraySize { array: usize, element: usize }, #[error("Due to size restrictions a struct could not be parsed.")] ImpossibleStructError, #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")] - InvalidEnumValueError { obj: String, field: String, value: u64, type_: String }, + InvalidEnumValueError { + obj: &'static str, + field: &'static str, + value: u64, + type_: &'static str, + }, + #[error("invalid field {packet}::{field} value, {expected} != {actual}")] + InvalidFieldValue { + packet: &'static str, + field: &'static str, + expected: &'static str, + actual: String, + }, #[error("expected child {expected}, got {actual}")] InvalidChildError { expected: &'static str, actual: String }, + #[error("packet has trailing bytes")] + TrailingBytes, + #[error("packet has trailing bytes inside {obj}.{field} array")] + TrailingBytesInArray { obj: &'static str, field: &'static str }, +} + +/// Type of serialization errors. +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum EncodeError { + #[error("the size of {packet}::{field} ({size}) is outside the range of valid values 0..{maximum_size}")] + SizeOverflow { packet: &'static str, field: &'static str, size: usize, maximum_size: usize }, + #[error( + "the count of {packet}::{field} ({count}) is outside the range of valid values 0..{maximum_count}" + )] + CountOverflow { packet: &'static str, field: &'static str, count: usize, maximum_count: usize }, + #[error( + "the value of {packet}::{field} ({value}) is outside the range of valid values 0..{maximum_value}" + )] + InvalidScalarValue { packet: &'static str, field: &'static str, value: u64, maximum_value: u64 }, + #[error( + "{packet}.{field}[{element_index}] size is {size}, but {expected_size} was expected (size of {packet}.{field}[0])" + )] + InvalidArrayElementSize { + packet: &'static str, + field: &'static str, + size: usize, + expected_size: usize, + element_index: usize, + }, } /// Trait implemented for all toplevel packet declarations. -pub trait Packet { - fn to_bytes(self) -> Bytes; - fn to_vec(self) -> Vec<u8>; +pub trait Packet: Sized { + /// Try parsing an instance of Self from the input slice. + /// On success, returns the parsed object and the remaining unparsed slice. + /// On failure, returns an error with the reason for the parsing failure. + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError>; + + /// Try parsing an instance of Packet updating the slice in place + /// to the remainder of the data. The input buffer is not updated if + /// parsing fails. + fn decode_mut(buf: &mut &[u8]) -> Result<Self, DecodeError> { + let (packet, remaining) = Self::decode(buf)?; + *buf = remaining; + Ok(packet) + } + + /// Try parsing an instance of Packet from the input slice. + /// Returns an error if unparsed bytes remain at the end of the input slice. + fn decode_full(buf: &[u8]) -> Result<Self, DecodeError> { + let (packet, remaining) = Self::decode(buf)?; + if remaining.is_empty() { + Ok(packet) + } else { + Err(DecodeError::TrailingBytes) + } + } + + /// Return the length of the encoded packet. + fn encoded_len(&self) -> usize; + + /// Write the packet to an output buffer. + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError>; + + /// Encode the packet to a byte vector. + fn encode_to_vec(&self) -> Result<Vec<u8>, EncodeError> { + let mut buf = Vec::with_capacity(self.encoded_len()); + self.encode(&mut buf)?; + Ok(buf) + } + + /// Encode the packet to a Bytes object. + fn encode_to_bytes(&self) -> Result<Bytes, EncodeError> { + let mut buf = BytesMut::with_capacity(self.encoded_len()); + self.encode(&mut buf)?; + Ok(buf.freeze()) + } } |