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, 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, thiserror::Error, PartialEq, Eq)]
58pub enum EncodeError {
59    #[error("the size of {packet}::{field} ({size}) is outside the range of valid values 0..{maximum_size}")]
60    SizeOverflow { packet: &'static str, field: &'static str, size: usize, maximum_size: usize },
61    #[error(
62        "the count of {packet}::{field} ({count}) is outside the range of valid values 0..{maximum_count}"
63    )]
64    CountOverflow { packet: &'static str, field: &'static str, count: usize, maximum_count: usize },
65    #[error(
66        "the value of {packet}::{field} ({value}) is outside the range of valid values 0..{maximum_value}"
67    )]
68    InvalidScalarValue { packet: &'static str, field: &'static str, value: u64, maximum_value: u64 },
69    #[error(
70        "{packet}.{field}[{element_index}] size is {size}, but {expected_size} was expected (size of {packet}.{field}[0])"
71    )]
72    InvalidArrayElementSize {
73        packet: &'static str,
74        field: &'static str,
75        size: usize,
76        expected_size: usize,
77        element_index: usize,
78    },
79    #[error("{packet}.{field} value cannot be uniquely determined")]
80    InconsistentConditionValue { packet: &'static str, field: &'static str },
81}
82
83/// Trait implemented for all toplevel packet declarations.
84pub trait Packet: Sized {
85    /// Try parsing an instance of Self from the input slice.
86    /// On success, returns the parsed object and the remaining unparsed slice.
87    /// On failure, returns an error with the reason for the parsing failure.
88    fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError>;
89
90    /// Try parsing an instance of Packet updating the slice in place
91    /// to the remainder of the data. The input buffer is not updated if
92    /// parsing fails.
93    fn decode_mut(buf: &mut &[u8]) -> Result<Self, DecodeError> {
94        let (packet, remaining) = Self::decode(buf)?;
95        *buf = remaining;
96        Ok(packet)
97    }
98
99    /// Try parsing an instance of Packet from the input slice.
100    /// Returns an error if unparsed bytes remain at the end of the input slice.
101    fn decode_full(buf: &[u8]) -> Result<Self, DecodeError> {
102        let (packet, remaining) = Self::decode(buf)?;
103        if remaining.is_empty() {
104            Ok(packet)
105        } else {
106            Err(DecodeError::TrailingBytes)
107        }
108    }
109
110    /// Return the length of the encoded packet.
111    fn encoded_len(&self) -> usize;
112
113    /// Write the packet to an output buffer.
114    fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError>;
115
116    /// Encode the packet to a byte vector.
117    fn encode_to_vec(&self) -> Result<Vec<u8>, EncodeError> {
118        let mut buf = Vec::with_capacity(self.encoded_len());
119        self.encode(&mut buf)?;
120        Ok(buf)
121    }
122
123    /// Encode the packet to a Bytes object.
124    fn encode_to_bytes(&self) -> Result<Bytes, EncodeError> {
125        let mut buf = BytesMut::with_capacity(self.encoded_len());
126        self.encode(&mut buf)?;
127        Ok(buf.freeze())
128    }
129}