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

facet-rs / facet / 14419675578

12 Apr 2025 12:38PM UTC coverage: 32.106%. Remained the same
14419675578

Pull #182

github

web-flow
Merge 38c518612 into b77265e32
Pull Request #182: Start working on facet-reflect missing docs

70 of 1394 new or added lines in 18 files covered. (5.02%)

445 existing lines in 15 files now uncovered.

2032 of 6329 relevant lines covered (32.11%)

13.47 hits per line

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

51.69
/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
/// ```
31
pub fn from_str<T: Facet>(msgpack: &[u8]) -> Result<T, DecodeError> {
1✔
32
    // Allocate a Poke for type T
33
    let (poke, _guard) = PokeUninit::alloc::<T>();
1✔
34

35
    // Deserialize the MessagePack into the Poke
36
    let opaque = from_slice_opaque(poke, msgpack)?;
2✔
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>(
1✔
85
    poke: PokeUninit<'mem>,
86
    msgpack: &[u8],
87
) -> Result<Opaque<'mem>, DecodeError> {
88
    let mut decoder = Decoder::new(msgpack);
1✔
89

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

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

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

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

UNCOV
131
        Ok(opaque)
×
132
    }
133

134
    deserialize_value(&mut decoder, poke)
1✔
135
}
136

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

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

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

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

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

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

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

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

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

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

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

UNCOV
250
        match prefix {
×
251
            prefix @ MSGPACK_FIXMAP_MIN..=MSGPACK_FIXMAP_MAX => Ok((prefix & 0x0f) as usize),
3✔
UNCOV
252
            MSGPACK_MAP16 => Ok(self.decode_u16()? as usize),
×
253
            MSGPACK_MAP32 => Ok(self.decode_u32()? as usize),
×
254
            _ => Err(DecodeError::UnexpectedType),
×
255
        }
256
    }
257
}
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