• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 14438796034

14 Apr 2025 06:17AM UTC coverage: 20.611% (-11.0%) from 31.623%
14438796034

Pull #188

github

web-flow
Merge 170ac71ca into 046ca7ecc
Pull Request #188: Rewrite facet-reflect for safety

492 of 1057 new or added lines in 44 files covered. (46.55%)

670 existing lines in 18 files now uncovered.

1228 of 5958 relevant lines covered (20.61%)

11.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/facet-msgpack/src/from_msgpack.rs
1
use crate::constants::*;
2
use crate::errors::Error as DecodeError;
3

4
use facet_core::{Facet, Opaque};
5
use facet_reflect::PokeUninit;
6
use log::trace;
7

8
/// Deserializes MessagePack-encoded data into a type that implements `Facet`.
9
///
10
/// # Example
11
/// ```
12
/// use facet::Facet;
13
/// use facet_msgpack::from_str;
14
///
15
/// #[derive(Debug, Facet, PartialEq)]
16
/// struct User {
17
///     id: u64,
18
///     username: String,
19
/// }
20
///
21
/// // MessagePack binary data (equivalent to {"id": 42, "username": "user123"})
22
/// let msgpack_data = [
23
///     0x82, 0xa2, 0x69, 0x64, 0x2a, 0xa8, 0x75, 0x73,
24
///     0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0xa7, 0x75,
25
///     0x73, 0x65, 0x72, 0x31, 0x32, 0x33
26
/// ];
27
///
28
/// let user: User = from_str(&msgpack_data).unwrap();
29
/// assert_eq!(user, User { id: 42, username: "user123".to_string() });
30
/// ```
UNCOV
31
pub fn from_str<T: Facet>(msgpack: &[u8]) -> Result<T, DecodeError> {
×
32
    // Allocate a Poke for type T
UNCOV
33
    let (poke, _guard) = PokeUninit::alloc::<T>();
×
34

35
    // Deserialize the MessagePack into the Poke
UNCOV
36
    let opaque = from_slice_opaque(poke, msgpack)?;
×
37

38
    // Convert the Opaque to the concrete type T
39
    let result = unsafe { opaque.read::<T>() };
×
40

41
    Ok(result)
×
42
}
43

44
/// Deserializes MessagePack-encoded data into a Facet Partial.
45
///
46
/// This function takes a MessagePack byte array and populates a Partial object
47
/// according to the shape description provided by the Partial.
48
///
49
/// # Example
50
///
51
/// ```
52
/// use facet::Facet;
53
/// use facet_msgpack::from_str;
54
///
55
/// #[derive(Debug, Facet, PartialEq)]
56
/// struct User {
57
///     id: u64,
58
///     username: String,
59
/// }
60
///
61
/// // MessagePack binary data (equivalent to {"id": 42, "username": "user123"})
62
/// let msgpack_data = [
63
///     0x82, 0xa2, 0x69, 0x64, 0x2a, 0xa8, 0x75, 0x73,
64
///     0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0xa7, 0x75,
65
///     0x73, 0x65, 0x72, 0x31, 0x32, 0x33
66
/// ];
67
///
68
/// let user: User = from_str(&msgpack_data).unwrap();
69
/// assert_eq!(user, User { id: 42, username: "user123".to_string() });
70
/// ```
71
///
72
/// # Parameters
73
/// * `partial` - A mutable reference to a Partial object that will be filled with deserialized data
74
/// * `msgpack` - A byte slice containing MessagePack-encoded data
75
///
76
/// # Returns
77
/// * `Ok(())` if deserialization was successful
78
/// * `Err(DecodeError)` if an error occurred during deserialization
79
///
80
/// # MessagePack Format
81
/// This implementation follows the MessagePack specification:
82
/// <https://github.com/msgpack/msgpack/blob/master/spec.md>
83
#[allow(clippy::needless_lifetimes)]
84
pub fn from_slice_opaque<'mem>(
85
    poke: PokeUninit<'mem>,
86
    msgpack: &[u8],
87
) -> Result<Opaque<'mem>, DecodeError> {
UNCOV
88
    let mut decoder = Decoder::new(msgpack);
×
89

UNCOV
90
    fn deserialize_value<'mem>(
×
91
        decoder: &mut Decoder,
92
        poke: PokeUninit<'mem>,
93
    ) -> Result<Opaque<'mem>, DecodeError> {
UNCOV
94
        let shape = poke.shape();
×
UNCOV
95
        trace!("Deserializing {:?}", shape);
×
96

UNCOV
97
        let opaque = match poke {
×
UNCOV
98
            PokeUninit::Scalar(pv) => {
×
UNCOV
99
                trace!("Deserializing scalar");
×
UNCOV
100
                if pv.shape().is_type::<String>() {
×
UNCOV
101
                    let s = decoder.decode_string()?;
×
102
                    let data = pv.put(s);
×
103
                    data
×
UNCOV
104
                } else if pv.shape().is_type::<u64>() {
×
UNCOV
105
                    let n = decoder.decode_u64()?;
×
106
                    pv.put(n)
×
107
                } else {
108
                    todo!("Unsupported scalar type: {}", pv.shape())
109
                }
110
                .data()
111
            }
UNCOV
112
            PokeUninit::Struct(mut ps) => {
×
UNCOV
113
                trace!("Deserializing struct");
×
UNCOV
114
                let map_len = decoder.decode_map_len()?;
×
115

116
                for _ in 0..map_len {
×
UNCOV
117
                    let key = decoder.decode_string()?;
×
UNCOV
118
                    let (index, field_poke) = ps
×
119
                        .field_by_name(&key)
×
120
                        .map_err(|_| DecodeError::UnknownField(key))?;
×
121

122
                    deserialize_value(decoder, field_poke)?;
×
UNCOV
123
                    unsafe { ps.mark_initialized(index) };
×
124
                }
UNCOV
125
                ps.build_in_place()
×
126
            }
127
            _ => {
×
128
                todo!("Unsupported shape: {:?}", shape)
129
            }
130
        };
131

132
        Ok(opaque)
×
133
    }
134

UNCOV
135
    deserialize_value(&mut decoder, poke)
×
136
}
137

138
struct Decoder<'input> {
139
    input: &'input [u8],
140
    offset: usize,
141
}
142

143
impl<'input> Decoder<'input> {
UNCOV
144
    fn new(input: &'input [u8]) -> Self {
×
145
        Decoder { input, offset: 0 }
146
    }
147

148
    /// Decodes a single byte from the input.
149
    /// This is a low-level method used by other decoders.
UNCOV
150
    fn decode_u8(&mut self) -> Result<u8, DecodeError> {
×
UNCOV
151
        if self.offset >= self.input.len() {
×
152
            return Err(DecodeError::InsufficientData);
×
153
        }
UNCOV
154
        let value = self.input[self.offset];
×
UNCOV
155
        self.offset += 1;
×
UNCOV
156
        Ok(value)
×
157
    }
158

159
    /// Decodes a 16-bit unsigned integer in big-endian byte order.
160
    /// This is a low-level method used by other decoders.
161
    fn decode_u16(&mut self) -> Result<u16, DecodeError> {
×
162
        if self.offset + 2 > self.input.len() {
×
163
            return Err(DecodeError::InsufficientData);
×
164
        }
165
        let value =
×
166
            u16::from_be_bytes(self.input[self.offset..self.offset + 2].try_into().unwrap());
×
167
        self.offset += 2;
×
168
        Ok(value)
×
169
    }
170

171
    /// Decodes a 32-bit unsigned integer in big-endian byte order.
172
    /// This is a low-level method used by other decoders.
UNCOV
173
    fn decode_u32(&mut self) -> Result<u32, DecodeError> {
×
UNCOV
174
        if self.offset + 4 > self.input.len() {
×
175
            return Err(DecodeError::InsufficientData);
×
176
        }
UNCOV
177
        let value =
×
UNCOV
178
            u32::from_be_bytes(self.input[self.offset..self.offset + 4].try_into().unwrap());
×
UNCOV
179
        self.offset += 4;
×
UNCOV
180
        Ok(value)
×
181
    }
182

183
    /// Decodes a MessagePack-encoded unsigned 64-bit integer.
184
    /// Handles the following MessagePack types:
185
    /// - positive fixint (0x00 - 0x7f): single-byte positive integer
186
    /// - uint8 (0xcc): 8-bit unsigned integer
187
    /// - uint16 (0xcd): 16-bit unsigned integer (big-endian)
188
    /// - uint32 (0xce): 32-bit unsigned integer (big-endian)
189
    /// - uint64 (0xcf): 64-bit unsigned integer (big-endian)
190
    ///
191
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#int-format-family>
UNCOV
192
    fn decode_u64(&mut self) -> Result<u64, DecodeError> {
×
UNCOV
193
        match self.decode_u8()? {
×
194
            MSGPACK_UINT8 => Ok(self.decode_u8()? as u64),
×
195
            MSGPACK_UINT16 => Ok(self.decode_u16()? as u64),
×
UNCOV
196
            MSGPACK_UINT32 => Ok(self.decode_u32()? as u64),
×
197
            MSGPACK_UINT64 => {
×
198
                if self.offset + 8 > self.input.len() {
×
199
                    return Err(DecodeError::InsufficientData);
×
200
                }
201
                let value = u64::from_be_bytes(
202
                    self.input[self.offset..self.offset + 8].try_into().unwrap(),
×
203
                );
204
                self.offset += 8;
×
205
                Ok(value)
×
206
            }
207
            prefix @ MSGPACK_POSFIXINT_MIN..=MSGPACK_POSFIXINT_MAX => Ok(prefix as u64),
×
208
            _ => Err(DecodeError::UnexpectedType),
×
209
        }
210
    }
211

212
    /// Decodes a MessagePack-encoded string.
213
    /// Handles the following MessagePack types:
214
    /// - fixstr (0xa0 - 0xbf): string up to 31 bytes
215
    /// - str8 (0xd9): string up to 255 bytes
216
    /// - str16 (0xda): string up to 65535 bytes
217
    /// - str32 (0xdb): string up to 4294967295 bytes
218
    ///
219
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str>
UNCOV
220
    fn decode_string(&mut self) -> Result<String, DecodeError> {
×
UNCOV
221
        let prefix = self.decode_u8()?;
×
222

UNCOV
223
        let len = match prefix {
×
UNCOV
224
            prefix @ MSGPACK_FIXSTR_MIN..=MSGPACK_FIXSTR_MAX => (prefix & 0x1f) as usize,
×
225
            MSGPACK_STR8 => self.decode_u8()? as usize,
×
226
            MSGPACK_STR16 => self.decode_u16()? as usize,
×
227
            MSGPACK_STR32 => self.decode_u32()? as usize,
×
228
            _ => return Err(DecodeError::UnexpectedType),
×
229
        };
230

231
        if self.offset + len > self.input.len() {
×
232
            return Err(DecodeError::InsufficientData);
×
233
        }
234

UNCOV
235
        let value = String::from_utf8(self.input[self.offset..self.offset + len].to_vec())
×
236
            .map_err(|_| DecodeError::InvalidData)?;
×
237
        self.offset += len;
×
238
        Ok(value)
×
239
    }
240

241
    /// Decodes a MessagePack-encoded map length.
242
    /// Handles the following MessagePack types:
243
    /// - fixmap (0x80 - 0x8f): map with up to 15 elements
244
    /// - map16 (0xde): map with up to 65535 elements
245
    /// - map32 (0xdf): map with up to 4294967295 elements
246
    ///
247
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#formats-map>
UNCOV
248
    fn decode_map_len(&mut self) -> Result<usize, DecodeError> {
×
UNCOV
249
        let prefix = self.decode_u8()?;
×
250

251
        match prefix {
×
UNCOV
252
            prefix @ MSGPACK_FIXMAP_MIN..=MSGPACK_FIXMAP_MAX => Ok((prefix & 0x0f) as usize),
×
253
            MSGPACK_MAP16 => Ok(self.decode_u16()? as usize),
×
254
            MSGPACK_MAP32 => Ok(self.decode_u32()? as usize),
×
255
            _ => Err(DecodeError::UnexpectedType),
×
256
        }
257
    }
258
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc