| // Copyright 2023 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| //! Helper definitions used used by the generated Rust backend. |
| |
| use bytes::{BufMut, Bytes, BytesMut}; |
| |
| /// Type of parsing errors. |
| #[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: &'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: &'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: &'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: 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()) |
| } |
| } |