bt_common/
packet_encoding.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use thiserror::Error;
6
7/// A decodable type can be created from a byte buffer.
8/// The type returned is separate (copied) from the buffer once decoded.
9pub trait Decodable: ::core::marker::Sized {
10    type Error;
11
12    /// Decodes into a new object or an error, and the number of bytes that
13    /// the decoding consumed.  Should attempt to consume the entire item from
14    /// the buffer in the case of an error.  If the item end cannot be determined,
15    /// return an error and consume the entirety of the bufer (`buf.len()`)
16    fn decode(buf: &[u8]) -> (::core::result::Result<Self, Self::Error>, usize);
17
18    /// Tries to decode a collection of this object concatenated in a buffer.
19    /// Returns a vector of items (or errors) and the number of bytes consumed to
20    /// decode them.
21    /// Continues to decode items until the buffer is consumed or the max items.
22    /// If None, will decode the entire buffer.
23    fn decode_multiple(
24        buf: &[u8],
25        max: Option<usize>,
26    ) -> (Vec<::core::result::Result<Self, Self::Error>>, usize) {
27        let mut idx = 0;
28        let mut result = Vec::new();
29        while idx < buf.len() && Some(result.len()) != max {
30            let (one_result, consumed) = Self::decode(&buf[idx..]);
31            result.push(one_result);
32            idx += consumed;
33        }
34        (result, idx)
35    }
36}
37
38/// A decodable type that has an exact size in bytes.
39pub trait FixedSizeDecodable: ::core::marker::Sized {
40    type Error;
41    const WRONG_SIZE_ERROR: Self::Error;
42    const BYTE_SIZE: usize;
43
44    /// Decodes the value.  This function assumes that buf is of at least
45    /// BYTE_SIZE, and assumes that BYTE_SIZE bytes are consumed to decode.
46    fn decode_checked(buf: &[u8]) -> core::result::Result<Self, Self::Error>;
47}
48
49/// An encodable type can write itself into a byte buffer.
50pub trait Encodable {
51    type Error;
52
53    /// Returns the number of bytes necessary to encode |self|.
54    fn encoded_len(&self) -> ::core::primitive::usize;
55
56    /// Writes the encoded version of |self| at the start of |buf|.
57    /// |buf| must be at least |self.encoded_len()| length.
58    fn encode(&self, buf: &mut [u8]) -> ::core::result::Result<(), Self::Error>;
59}
60
61/// Generates an enum value where each variant can be converted into a constant
62/// in the given raw_type.
63///
64/// For example:
65/// decodable_enum! {
66///     pub(crate) enum Color<u8, MyError, Variant> {
67///        Red = 1,
68///        Blue = 2,
69///        Green = 3,
70///     }
71/// }
72///
73/// Color::try_from(2) -> Color::Red
74/// u8::from(&Color::Red) -> 1.
75#[macro_export]
76macro_rules! decodable_enum {
77    ($(#[$meta:meta])* $visibility:vis enum $name:ident<
78        $raw_type:ty,
79        $error_type:ty,
80        $error_path:ident
81    > {
82        $($(#[$variant_meta:meta])* $variant:ident = $val:expr),*,
83    }) => {
84        $(#[$meta])*
85        #[derive(
86            ::core::clone::Clone,
87            ::core::marker::Copy,
88            ::core::fmt::Debug,
89            ::core::cmp::Eq,
90            ::core::hash::Hash,
91            ::core::cmp::PartialEq)]
92        $visibility enum $name {
93            $($(#[$variant_meta])* $variant = $val),*
94        }
95
96        impl $name {
97            pub const VALUES : &'static [$raw_type] = &[$($val),*,];
98            pub const VARIANTS : &'static [$name] = &[$($name::$variant),*,];
99            pub fn name(&self) -> &'static ::core::primitive::str {
100                match self {
101                    $($name::$variant => ::core::stringify!($variant)),*
102                }
103            }
104        }
105
106        impl ::core::convert::From<$name> for $raw_type {
107            fn from(v: $name) -> $raw_type {
108                match v {
109                    $($name::$variant => $val),*,
110                }
111            }
112        }
113
114        impl ::core::convert::TryFrom<$raw_type> for $name {
115            type Error = $error_type;
116
117            fn try_from(value: $raw_type) -> ::core::result::Result<Self, $error_type> {
118                match value {
119                    $($val => ::core::result::Result::Ok($name::$variant)),*,
120                    _ => ::core::result::Result::Err(<$error_type>::$error_path),
121                }
122            }
123        }
124    }
125}
126
127#[macro_export]
128macro_rules! codable_as_bitmask {
129    ($type:ty, $raw_type:ty) => {
130        impl $type {
131            pub fn from_bits(v: $raw_type) -> impl Iterator<Item = $type> {
132                (0..<$raw_type>::BITS)
133                    .map(|bit| 1 << bit)
134                    .filter(move |val| (v & val) != 0)
135                    .filter_map(|val| val.try_into().ok())
136            }
137
138            pub fn to_bits<'a>(it: impl Iterator<Item = &'a $type>) -> $raw_type {
139                it.fold(0, |acc, item| acc | Into::<$raw_type>::into(*item))
140            }
141        }
142    };
143}
144
145#[derive(Error, Debug, PartialEq)]
146pub enum Error {
147    #[error("Parameter is not valid: {0}")]
148    InvalidParameter(String),
149
150    #[error("Out-of-range enum value")]
151    OutOfRange,
152
153    #[error("Encoding buffer is too small")]
154    BufferTooSmall,
155
156    #[error("Buffer being decoded is invalid length")]
157    UnexpectedDataLength,
158
159    #[error("Unrecognized type for {0}: {1}")]
160    UnrecognizedType(String, u8),
161
162    #[error("Uuid parsing error: {0}")]
163    Uuid(uuid::Error),
164}