messagepack_core/extension/
mod.rs1mod decode;
4mod encode;
5
6use crate::decode::Error as DecodeError;
7use crate::{formats::Format, io::IoRead};
8
9const U8_MAX: usize = u8::MAX as usize;
10const U16_MAX: usize = u16::MAX as usize;
11const U32_MAX: usize = u32::MAX as usize;
12const U8_MAX_PLUS_ONE: usize = U8_MAX + 1;
13const U16_MAX_PLUS_ONE: usize = U16_MAX + 1;
14
15pub(crate) fn read_ext_header<'de, R>(
17 format: Format,
18 reader: &mut R,
19) -> Result<(usize, i8), DecodeError<R::Error>>
20where
21 R: IoRead<'de>,
22{
23 use crate::decode::NbyteReader;
24 let len = match format {
25 Format::FixExt1 => 1,
26 Format::FixExt2 => 2,
27 Format::FixExt4 => 4,
28 Format::FixExt8 => 8,
29 Format::FixExt16 => 16,
30 Format::Ext8 => NbyteReader::<1>::read(reader)?,
31 Format::Ext16 => NbyteReader::<2>::read(reader)?,
32 Format::Ext32 => NbyteReader::<4>::read(reader)?,
33 _ => return Err(DecodeError::UnexpectedFormat),
34 };
35
36 let ext_type: [u8; 1] = reader
37 .read_slice(1)
38 .map_err(DecodeError::Io)?
39 .as_bytes()
40 .try_into()
41 .map_err(|_| DecodeError::UnexpectedEof)?;
42 let ty = ext_type[0] as i8;
43
44 Ok((len, ty))
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
52pub struct ExtensionRef<'a> {
53 pub r#type: i8,
55 pub data: &'a [u8],
57}
58
59impl<'a> ExtensionRef<'a> {
60 pub fn new(r#type: i8, data: &'a [u8]) -> Self {
62 Self { r#type, data }
63 }
64
65 pub fn to_format<E>(&self) -> core::result::Result<Format, crate::encode::Error<E>> {
70 let format = match self.data.len() {
71 1 => Format::FixExt1,
72 2 => Format::FixExt2,
73 4 => Format::FixExt4,
74 8 => Format::FixExt8,
75 16 => Format::FixExt16,
76 0..=U8_MAX => Format::Ext8,
77 U8_MAX_PLUS_ONE..=U16_MAX => Format::Ext16,
78 U16_MAX_PLUS_ONE..=U32_MAX => Format::Ext32,
79 _ => return Err(crate::encode::Error::InvalidFormat),
80 };
81 Ok(format)
82 }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
93pub struct FixedExtension<const N: usize> {
94 pub r#type: i8,
96 len: usize,
97 data: [u8; N],
98}
99
100#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
102pub struct ExtensionCapacityError(());
103
104impl<const N: usize> FixedExtension<N> {
105 pub fn new(r#type: i8, data: &[u8]) -> Option<Self> {
110 if data.len() > N {
111 return None;
112 }
113 let mut buf = [0u8; N];
114 buf[..data.len()].copy_from_slice(data);
115 Some(Self {
116 r#type,
117 len: data.len(),
118 data: buf,
119 })
120 }
121 pub fn new_fixed(r#type: i8, data: [u8; N]) -> Self {
123 Self {
124 r#type,
125 len: N,
126 data,
127 }
128 }
129
130 pub fn new_fixed_with_prefix(
132 r#type: i8,
133 len: usize,
134 data: [u8; N],
135 ) -> core::result::Result<Self, ExtensionCapacityError> {
136 if len <= N {
137 Ok(Self { r#type, len, data })
138 } else {
139 Err(ExtensionCapacityError(()))
140 }
141 }
142
143 pub fn as_ref(&self) -> ExtensionRef<'_> {
145 ExtensionRef {
146 r#type: self.r#type,
147 data: &self.data[..self.len],
148 }
149 }
150
151 pub fn len(&self) -> usize {
153 self.len
154 }
155
156 pub fn is_empty(&self) -> bool {
158 self.len == 0
159 }
160
161 pub fn as_slice(&self) -> &[u8] {
163 &self.data[..self.len]
164 }
165
166 pub fn as_mut_slice(&mut self) -> &mut [u8] {
168 &mut self.data[..self.len]
169 }
170}
171
172impl core::fmt::Display for ExtensionCapacityError {
173 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
174 write!(f, "extension data exceeds capacity")
175 }
176}
177
178impl core::error::Error for ExtensionCapacityError {}
179
180impl<const N: usize> TryFrom<ExtensionRef<'_>> for FixedExtension<N> {
181 type Error = ExtensionCapacityError;
182
183 fn try_from(value: ExtensionRef<'_>) -> Result<Self, Self::Error> {
184 if value.data.len() > N {
185 return Err(ExtensionCapacityError(()));
186 }
187 let mut buf = [0u8; N];
188 buf[..value.data.len()].copy_from_slice(value.data);
189 Ok(Self {
190 r#type: value.r#type,
191 len: value.data.len(),
192 data: buf,
193 })
194 }
195}
196
197#[cfg(feature = "alloc")]
198mod owned {
199 use super::*;
200
201 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
203 pub struct ExtensionOwned {
204 pub r#type: i8,
206 pub data: alloc::vec::Vec<u8>,
208 }
209
210 impl ExtensionOwned {
211 pub fn new(r#type: i8, data: alloc::vec::Vec<u8>) -> Self {
213 Self { r#type, data }
214 }
215
216 pub fn as_ref(&self) -> ExtensionRef<'_> {
218 ExtensionRef {
219 r#type: self.r#type,
220 data: &self.data,
221 }
222 }
223 }
224
225 impl<'a> From<ExtensionRef<'a>> for ExtensionOwned {
226 fn from(value: ExtensionRef<'a>) -> Self {
227 Self {
228 r#type: value.r#type,
229 data: value.data.to_vec(),
230 }
231 }
232 }
233
234 impl<const N: usize> From<FixedExtension<N>> for ExtensionOwned {
235 fn from(value: FixedExtension<N>) -> Self {
236 Self {
237 r#type: value.r#type,
238 data: value.as_slice().to_vec(),
239 }
240 }
241 }
242}
243
244#[cfg(feature = "alloc")]
245pub use owned::ExtensionOwned;