bt_common/
packet_encoding.rs1use thiserror::Error;
6
7pub trait Decodable: ::core::marker::Sized {
10 type Error;
11
12 fn decode(buf: &[u8]) -> (::core::result::Result<Self, Self::Error>, usize);
17
18 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
38pub trait FixedSizeDecodable: ::core::marker::Sized {
40 type Error;
41 const WRONG_SIZE_ERROR: Self::Error;
42 const BYTE_SIZE: usize;
43
44 fn decode_checked(buf: &[u8]) -> core::result::Result<Self, Self::Error>;
47}
48
49pub trait Encodable {
51 type Error;
52
53 fn encoded_len(&self) -> ::core::primitive::usize;
55
56 fn encode(&self, buf: &mut [u8]) -> ::core::result::Result<(), Self::Error>;
59}
60
61#[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}