Skip to main content

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