Skip to main content

pdl_runtime/
lib.rs

1// Copyright 2023 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Helper definitions used used by the generated Rust backend.
16
17use bytes::{BufMut, Bytes, BytesMut};
18
19/// Type of parsing errors.
20#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
21pub enum DecodeError {
22    #[error("packet parsing failed")]
23    InvalidPacketError,
24    #[error("{field} was {value:x}, which is not known")]
25    ConstraintOutOfBounds { field: &'static str, value: u64 },
26    #[error("Got {actual:x}, expected {expected:x}")]
27    InvalidFixedValue { expected: u64, actual: u64 },
28    #[error("when parsing {obj} needed length of {wanted} but got {got}")]
29    InvalidLengthError { obj: &'static str, wanted: usize, got: usize },
30    #[error("array size ({array} bytes) is not a multiple of the element size ({element} bytes)")]
31    InvalidArraySize { array: usize, element: usize },
32    #[error("Due to size restrictions a struct could not be parsed.")]
33    ImpossibleStructError,
34    #[error("when parsing field {obj}.{field}, {value} is not a valid {type_} value")]
35    InvalidEnumValueError {
36        obj: &'static str,
37        field: &'static str,
38        value: u64,
39        type_: &'static str,
40    },
41    #[error("invalid field {packet}::{field} value, {expected} != {actual}")]
42    InvalidFieldValue {
43        packet: &'static str,
44        field: &'static str,
45        expected: &'static str,
46        actual: String,
47    },
48    #[error("expected child {expected}, got {actual}")]
49    InvalidChildError { expected: &'static str, actual: String },
50    #[error("packet has trailing bytes")]
51    TrailingBytes,
52    #[error("packet has trailing bytes inside {obj}.{field} array")]
53    TrailingBytesInArray { obj: &'static str, field: &'static str },
54}
55
56/// Type of serialization errors.
57#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
58pub enum EncodeError {
59    #[error(
60        "the size of {packet}::{field} ({size}) is outside the range of valid values 0..{maximum_size}"
61    )]
62    SizeOverflow { packet: &'static str, field: &'static str, size: usize, maximum_size: usize },
63    #[error(
64        "the count of {packet}::{field} ({count}) is outside the range of valid values 0..{maximum_count}"
65    )]
66    CountOverflow { packet: &'static str, field: &'static str, count: usize, maximum_count: usize },
67    #[error(
68        "the value of {packet}::{field} ({value}) is outside the range of valid values 0..{maximum_value}"
69    )]
70    InvalidScalarValue { packet: &'static str, field: &'static str, value: u64, maximum_value: u64 },
71    #[error(
72        "{packet}.{field}[{element_index}] size is {size}, but {expected_size} was expected (size of {packet}.{field}[0])"
73    )]
74    InvalidArrayElementSize {
75        packet: &'static str,
76        field: &'static str,
77        size: usize,
78        expected_size: usize,
79        element_index: usize,
80    },
81    #[error("{packet}.{field} value cannot be uniquely determined")]
82    InconsistentConditionValue { packet: &'static str, field: &'static str },
83}
84
85/// Trait implemented for all toplevel packet declarations.
86pub trait Packet: Sized {
87    /// Try parsing an instance of Self from the input slice.
88    /// On success, returns the parsed object and the remaining unparsed slice.
89    /// On failure, returns an error with the reason for the parsing failure.
90    fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError>;
91
92    /// Try parsing an instance of Packet updating the slice in place
93    /// to the remainder of the data. The input buffer is not updated if
94    /// parsing fails.
95    fn decode_mut(buf: &mut &[u8]) -> Result<Self, DecodeError> {
96        let (packet, remaining) = Self::decode(buf)?;
97        *buf = remaining;
98        Ok(packet)
99    }
100
101    /// Try parsing an instance of Packet from the input slice.
102    /// Returns an error if unparsed bytes remain at the end of the input slice.
103    fn decode_full(buf: &[u8]) -> Result<Self, DecodeError> {
104        let (packet, remaining) = Self::decode(buf)?;
105        if remaining.is_empty() { Ok(packet) } else { Err(DecodeError::TrailingBytes) }
106    }
107
108    /// Return the length of the encoded packet.
109    fn encoded_len(&self) -> usize;
110
111    /// Write the packet to an output buffer.
112    fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError>;
113
114    /// Encode the packet to a byte vector.
115    fn encode_to_vec(&self) -> Result<Vec<u8>, EncodeError> {
116        let mut buf = Vec::with_capacity(self.encoded_len());
117        self.encode(&mut buf)?;
118        Ok(buf)
119    }
120
121    /// Encode the packet to a Bytes object.
122    fn encode_to_bytes(&self) -> Result<Bytes, EncodeError> {
123        let mut buf = BytesMut::with_capacity(self.encoded_len());
124        self.encode(&mut buf)?;
125        Ok(buf.freeze())
126    }
127}