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

facet-rs / facet / 15022217137

14 May 2025 01:38PM UTC coverage: 59.025% (+0.4%) from 58.592%
15022217137

Pull #614

github

web-flow
Merge c537e58cd into 7c93673e1
Pull Request #614: Introduce `facet_testhelpers::test` attribute

175 of 252 new or added lines in 3 files covered. (69.44%)

1 existing line in 1 file now uncovered.

10105 of 17120 relevant lines covered (59.02%)

122.48 hits per line

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

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

4
use facet_core::{Def, Facet, Type, UserType};
5
use facet_reflect::{HeapValue, Wip};
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_slice<'input: 'facet, 'facet, T: Facet<'facet>>(
21✔
32
    msgpack: &'input [u8],
21✔
33
) -> Result<T, DecodeError> {
21✔
34
    from_slice_value(Wip::alloc::<T>()?, msgpack)?
21✔
35
        .materialize::<T>()
19✔
36
        .map_err(|e| DecodeError::UnsupportedType(e.to_string()))
19✔
37
}
21✔
38

39
/// Alias for from_slice for backward compatibility
40
#[deprecated(since = "0.1.0", note = "Use from_slice instead")]
41
pub fn from_str<'input: 'facet, 'facet, T: Facet<'facet>>(
×
42
    msgpack: &'input [u8],
×
43
) -> Result<T, DecodeError> {
×
44
    from_slice(msgpack)
×
45
}
×
46

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

98
struct Decoder<'input> {
99
    input: &'input [u8],
100
    offset: usize,
101
}
102

103
impl<'input> Decoder<'input> {
104
    fn new(input: &'input [u8]) -> Self {
23✔
105
        Decoder { input, offset: 0 }
23✔
106
    }
23✔
107

108
    /// Decodes a single byte from the input.
109
    /// This is a low-level method used by other decoders.
110
    fn decode_u8(&mut self) -> Result<u8, DecodeError> {
96✔
111
        if self.offset >= self.input.len() {
96✔
112
            return Err(DecodeError::InsufficientData);
1✔
113
        }
95✔
114
        let value = self.input[self.offset];
95✔
115
        self.offset += 1;
95✔
116
        Ok(value)
95✔
117
    }
96✔
118

119
    /// Decodes a 16-bit unsigned integer in big-endian byte order.
120
    /// This is a low-level method used by other decoders.
121
    fn decode_u16(&mut self) -> Result<u16, DecodeError> {
1✔
122
        if self.offset + 2 > self.input.len() {
1✔
123
            return Err(DecodeError::InsufficientData);
×
124
        }
1✔
125
        let value =
1✔
126
            u16::from_be_bytes(self.input[self.offset..self.offset + 2].try_into().unwrap());
1✔
127
        self.offset += 2;
1✔
128
        Ok(value)
1✔
129
    }
1✔
130

131
    /// Decodes a 32-bit unsigned integer in big-endian byte order.
132
    /// This is a low-level method used by other decoders.
133
    fn decode_u32(&mut self) -> Result<u32, DecodeError> {
3✔
134
        if self.offset + 4 > self.input.len() {
3✔
135
            return Err(DecodeError::InsufficientData);
×
136
        }
3✔
137
        let value =
3✔
138
            u32::from_be_bytes(self.input[self.offset..self.offset + 4].try_into().unwrap());
3✔
139
        self.offset += 4;
3✔
140
        Ok(value)
3✔
141
    }
3✔
142

143
    /// Decodes a MessagePack-encoded unsigned 64-bit integer.
144
    /// Handles the following MessagePack types:
145
    /// - positive fixint (0x00 - 0x7f): single-byte positive integer
146
    /// - uint8 (0xcc): 8-bit unsigned integer
147
    /// - uint16 (0xcd): 16-bit unsigned integer (big-endian)
148
    /// - uint32 (0xce): 32-bit unsigned integer (big-endian)
149
    /// - uint64 (0xcf): 64-bit unsigned integer (big-endian)
150
    ///
151
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#int-format-family>
152
    fn decode_u64(&mut self) -> Result<u64, DecodeError> {
22✔
153
        match self.decode_u8()? {
22✔
154
            MSGPACK_UINT8 => Ok(self.decode_u8()? as u64),
×
155
            MSGPACK_UINT16 => Ok(self.decode_u16()? as u64),
1✔
156
            MSGPACK_UINT32 => Ok(self.decode_u32()? as u64),
3✔
157
            MSGPACK_UINT64 => {
158
                if self.offset + 8 > self.input.len() {
×
159
                    return Err(DecodeError::InsufficientData);
×
160
                }
×
161
                let value = u64::from_be_bytes(
×
162
                    self.input[self.offset..self.offset + 8].try_into().unwrap(),
×
163
                );
×
164
                self.offset += 8;
×
165
                Ok(value)
×
166
            }
167
            prefix @ MSGPACK_POSFIXINT_MIN..=MSGPACK_POSFIXINT_MAX => Ok(prefix as u64),
18✔
168
            _ => Err(DecodeError::UnexpectedType),
×
169
        }
170
    }
22✔
171

172
    /// Decodes a MessagePack-encoded string.
173
    /// Handles the following MessagePack types:
174
    /// - fixstr (0xa0 - 0xbf): string up to 31 bytes
175
    /// - str8 (0xd9): string up to 255 bytes
176
    /// - str16 (0xda): string up to 65535 bytes
177
    /// - str32 (0xdb): string up to 4294967295 bytes
178
    ///
179
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str>
180
    fn decode_string(&mut self) -> Result<String, DecodeError> {
43✔
181
        let prefix = self.decode_u8()?;
43✔
182

183
        let len = match prefix {
42✔
184
            prefix @ MSGPACK_FIXSTR_MIN..=MSGPACK_FIXSTR_MAX => (prefix & 0x1f) as usize,
42✔
185
            MSGPACK_STR8 => self.decode_u8()? as usize,
×
186
            MSGPACK_STR16 => self.decode_u16()? as usize,
×
187
            MSGPACK_STR32 => self.decode_u32()? as usize,
×
188
            _ => return Err(DecodeError::UnexpectedType),
1✔
189
        };
190

191
        if self.offset + len > self.input.len() {
41✔
192
            return Err(DecodeError::InsufficientData);
×
193
        }
41✔
194

195
        let value = String::from_utf8(self.input[self.offset..self.offset + len].to_vec())
41✔
196
            .map_err(|_| DecodeError::InvalidData)?;
41✔
197
        self.offset += len;
41✔
198
        Ok(value)
41✔
199
    }
43✔
200

201
    /// Decodes a MessagePack-encoded map length.
202
    /// Handles the following MessagePack types:
203
    /// - fixmap (0x80 - 0x8f): map with up to 15 elements
204
    /// - map16 (0xde): map with up to 65535 elements
205
    /// - map32 (0xdf): map with up to 4294967295 elements
206
    ///
207
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#formats-map>
208
    fn decode_map_len(&mut self) -> Result<usize, DecodeError> {
16✔
209
        let prefix = self.decode_u8()?;
16✔
210

211
        match prefix {
16✔
212
            prefix @ MSGPACK_FIXMAP_MIN..=MSGPACK_FIXMAP_MAX => Ok((prefix & 0x0f) as usize),
16✔
213
            MSGPACK_MAP16 => Ok(self.decode_u16()? as usize),
×
214
            MSGPACK_MAP32 => Ok(self.decode_u32()? as usize),
×
215
            _ => Err(DecodeError::UnexpectedType),
×
216
        }
217
    }
16✔
218

219
    /// Decodes a MessagePack-encoded array length.
220
    /// Handles the following MessagePack types:
221
    /// - fixarray (0x90 - 0x9f): array with up to 15 elements
222
    /// - array16 (0xdc): array with up to 65535 elements
223
    /// - array32 (0xdd): array with up to 4294967295 elements
224
    ///
225
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#formats-array>
226
    #[allow(dead_code)]
227
    fn decode_array_len(&mut self) -> Result<usize, DecodeError> {
11✔
228
        let prefix = self.decode_u8()?;
11✔
229

230
        match prefix {
11✔
231
            prefix @ MSGPACK_FIXARRAY_MIN..=MSGPACK_FIXARRAY_MAX => Ok((prefix & 0x0f) as usize),
11✔
232
            MSGPACK_ARRAY16 => Ok(self.decode_u16()? as usize),
×
233
            MSGPACK_ARRAY32 => Ok(self.decode_u32()? as usize),
×
234
            _ => Err(DecodeError::UnexpectedType),
×
235
        }
236
    }
11✔
237

238
    /// Decodes a MessagePack-encoded boolean value.
239
    /// Handles the following MessagePack types:
240
    /// - true (0xc3): boolean true
241
    /// - false (0xc2): boolean false
242
    ///
243
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#formats-bool>
244
    fn decode_bool(&mut self) -> Result<bool, DecodeError> {
3✔
245
        match self.decode_u8()? {
3✔
246
            MSGPACK_TRUE => Ok(true),
1✔
247
            MSGPACK_FALSE => Ok(false),
2✔
248
            _ => Err(DecodeError::UnexpectedType),
×
249
        }
250
    }
3✔
251

252
    /// Decodes a MessagePack-encoded nil value.
253
    /// Handles the following MessagePack types:
254
    /// - nil (0xc0): nil/null value
255
    ///
256
    /// Ref: <https://github.com/msgpack/msgpack/blob/master/spec.md#formats-nil>
257
    #[allow(dead_code)]
258
    fn decode_nil(&mut self) -> Result<(), DecodeError> {
1✔
259
        match self.decode_u8()? {
1✔
260
            MSGPACK_NIL => Ok(()),
1✔
261
            _ => Err(DecodeError::UnexpectedType),
×
262
        }
263
    }
1✔
264

265
    /// Peeks at the next byte to check if it's a nil value without advancing the offset.
266
    /// Returns true if the next value is nil, false otherwise.
267
    #[allow(dead_code)]
268
    fn peek_nil(&mut self) -> Result<bool, DecodeError> {
3✔
269
        if self.offset >= self.input.len() {
3✔
270
            return Err(DecodeError::InsufficientData);
×
271
        }
3✔
272
        Ok(self.input[self.offset] == MSGPACK_NIL)
3✔
273
    }
3✔
274

275
    /// Peeks at the next byte to check if it's a string value without advancing the offset.
276
    /// Returns true if the next value is a string, false otherwise.
277
    fn peek_string(&mut self) -> Result<bool, DecodeError> {
3✔
278
        if self.offset >= self.input.len() {
3✔
NEW
279
            return Err(DecodeError::InsufficientData);
×
280
        }
3✔
281
        let prefix = self.input[self.offset];
3✔
282
        Ok((MSGPACK_FIXSTR_MIN..=MSGPACK_FIXSTR_MAX).contains(&prefix)
3✔
283
            || prefix == MSGPACK_STR8
1✔
284
            || prefix == MSGPACK_STR16
1✔
285
            || prefix == MSGPACK_STR32)
1✔
286
    }
3✔
287

288
    /// Skips a MessagePack value of any type.
289
    /// This is used when encountering unknown field names in a struct.
290
    fn skip_value(&mut self) -> Result<(), DecodeError> {
×
291
        let prefix = self.decode_u8()?;
×
292

293
        match prefix {
×
294
            // String formats
295
            prefix @ MSGPACK_FIXSTR_MIN..=MSGPACK_FIXSTR_MAX => {
×
296
                let len = (prefix & 0x1f) as usize;
×
297
                if self.offset + len > self.input.len() {
×
298
                    return Err(DecodeError::InsufficientData);
×
299
                }
×
300
                self.offset += len;
×
301
                Ok(())
×
302
            }
303
            MSGPACK_STR8 => {
304
                let len = self.decode_u8()? as usize;
×
305
                if self.offset + len > self.input.len() {
×
306
                    return Err(DecodeError::InsufficientData);
×
307
                }
×
308
                self.offset += len;
×
309
                Ok(())
×
310
            }
311
            MSGPACK_STR16 => {
312
                let len = self.decode_u16()? as usize;
×
313
                if self.offset + len > self.input.len() {
×
314
                    return Err(DecodeError::InsufficientData);
×
315
                }
×
316
                self.offset += len;
×
317
                Ok(())
×
318
            }
319
            MSGPACK_STR32 => {
320
                let len = self.decode_u32()? as usize;
×
321
                if self.offset + len > self.input.len() {
×
322
                    return Err(DecodeError::InsufficientData);
×
323
                }
×
324
                self.offset += len;
×
325
                Ok(())
×
326
            }
327

328
            // Integer formats
329
            MSGPACK_UINT8 => {
330
                self.offset += 1;
×
331
                Ok(())
×
332
            }
333
            MSGPACK_UINT16 => {
334
                self.offset += 2;
×
335
                Ok(())
×
336
            }
337
            MSGPACK_UINT32 => {
338
                self.offset += 4;
×
339
                Ok(())
×
340
            }
341
            MSGPACK_UINT64 => {
342
                self.offset += 8;
×
343
                Ok(())
×
344
            }
345
            MSGPACK_INT8 => {
346
                self.offset += 1;
×
347
                Ok(())
×
348
            }
349
            MSGPACK_INT16 => {
350
                self.offset += 2;
×
351
                Ok(())
×
352
            }
353
            MSGPACK_INT32 => {
354
                self.offset += 4;
×
355
                Ok(())
×
356
            }
357
            MSGPACK_INT64 => {
358
                self.offset += 8;
×
359
                Ok(())
×
360
            }
361
            // Fixed integers are already handled by decode_u8
362

363
            // Boolean and nil
364
            MSGPACK_NIL | MSGPACK_TRUE | MSGPACK_FALSE => Ok(()),
×
365

366
            // Map format
367
            prefix @ MSGPACK_FIXMAP_MIN..=MSGPACK_FIXMAP_MAX => {
×
368
                let len = (prefix & 0x0f) as usize;
×
369
                for _ in 0..len {
×
370
                    self.skip_value()?; // Skip key
×
371
                    self.skip_value()?; // Skip value
×
372
                }
373
                Ok(())
×
374
            }
375
            MSGPACK_MAP16 => {
376
                let len = self.decode_u16()? as usize;
×
377
                for _ in 0..len {
×
378
                    self.skip_value()?; // Skip key
×
379
                    self.skip_value()?; // Skip value
×
380
                }
381
                Ok(())
×
382
            }
383
            MSGPACK_MAP32 => {
384
                let len = self.decode_u32()? as usize;
×
385
                for _ in 0..len {
×
386
                    self.skip_value()?; // Skip key
×
387
                    self.skip_value()?; // Skip value
×
388
                }
389
                Ok(())
×
390
            }
391

392
            // Array format
393
            prefix @ MSGPACK_FIXARRAY_MIN..=MSGPACK_FIXARRAY_MAX => {
×
394
                let len = (prefix & 0x0f) as usize;
×
395
                for _ in 0..len {
×
396
                    self.skip_value()?;
×
397
                }
398
                Ok(())
×
399
            }
400
            MSGPACK_ARRAY16 => {
401
                let len = self.decode_u16()? as usize;
×
402
                for _ in 0..len {
×
403
                    self.skip_value()?;
×
404
                }
405
                Ok(())
×
406
            }
407
            MSGPACK_ARRAY32 => {
408
                let len = self.decode_u32()? as usize;
×
409
                for _ in 0..len {
×
410
                    self.skip_value()?;
×
411
                }
412
                Ok(())
×
413
            }
414

415
            _ => Err(DecodeError::UnexpectedType),
×
416
        }
417
    }
×
418

419
    fn deserialize_value(&mut self, mut wip: Wip<'input>) -> Result<Wip<'input>, DecodeError> {
74✔
420
        let shape = wip.shape();
74✔
421
        trace!("Deserializing {:?}", shape);
74✔
422

423
        // First check the type system (Type)
424
        match &shape.ty {
5✔
425
            Type::User(UserType::Struct(struct_type)) => {
12✔
426
                trace!("Deserializing struct");
12✔
427
                let map_len = self.decode_map_len()?;
12✔
428

429
                // Track which fields we've seen so we can handle defaults for the rest
430
                let mut seen_fields = vec![false; struct_type.fields.len()];
12✔
431

12✔
432
                let mut wip = wip;
12✔
433
                for _ in 0..map_len {
12✔
434
                    let key = self.decode_string()?;
19✔
435
                    match wip.field_index(&key) {
18✔
436
                        Some(index) => {
18✔
437
                            seen_fields[index] = true;
18✔
438
                            wip = self
18✔
439
                                .deserialize_value(wip.field(index).unwrap())?
18✔
440
                                .pop()
17✔
441
                                .unwrap();
17✔
442
                        }
443
                        None => {
444
                            // Skip unknown field value
NEW
445
                            self.skip_value()?;
×
NEW
446
                            trace!("Skipping unknown field: {}", key);
×
447
                        }
448
                    }
449
                }
450

451
                // Handle defaults for fields that weren't seen in the input
452
                for (i, &seen) in seen_fields.iter().enumerate() {
16✔
453
                    if !seen {
16✔
454
                        let field = &struct_type.fields[i];
1✔
455
                        if field.flags.contains(facet_core::FieldFlags::DEFAULT) {
1✔
456
                            // Field has default attribute, so we should apply the default
457
                            let field_wip = wip.field(i).map_err(DecodeError::ReflectError)?;
1✔
458

459
                            // Whether there's a custom default function or not, we just use put_default()
460
                            // the Wip.put_default() API in the facet system will handle calling the
461
                            // appropriate default function set in the #[facet(default = ...)] attribute
462
                            wip = field_wip
1✔
463
                                .put_default()
1✔
464
                                .map_err(DecodeError::ReflectError)?
1✔
465
                                .pop()
1✔
466
                                .map_err(DecodeError::ReflectError)?;
1✔
467
                        } else {
468
                            // Non-default field was missing
NEW
469
                            return Err(DecodeError::MissingField(field.name.to_string()));
×
470
                        }
471
                    }
15✔
472
                }
473

474
                return Ok(wip);
10✔
475
            }
476
            Type::Sequence(facet_core::SequenceType::Tuple(tuple_type)) => {
5✔
477
                trace!("Deserializing tuple");
5✔
478
                let array_len = self.decode_array_len()?;
5✔
479
                let field_count = tuple_type.fields.len();
5✔
480

5✔
481
                if array_len != field_count {
5✔
NEW
482
                    return Err(DecodeError::InvalidData);
×
483
                }
5✔
484

485
                // For tuples, we need to use begin_pushback for the new API
486
                let mut tuple_wip = wip.begin_pushback().map_err(DecodeError::ReflectError)?;
5✔
487

488
                for _ in 0..field_count {
5✔
489
                    // Push a new element
490
                    let element_wip = tuple_wip.push().map_err(DecodeError::ReflectError)?;
9✔
491

492
                    // Deserialize the element value
493
                    let element_wip = self.deserialize_value(element_wip)?;
9✔
494

495
                    // Pop back up to the tuple level
496
                    tuple_wip = element_wip.pop().map_err(DecodeError::ReflectError)?;
9✔
497
                }
498

499
                return Ok(tuple_wip);
5✔
500
            }
501
            Type::User(UserType::Enum(enum_type)) => {
3✔
502
                trace!("Deserializing enum");
3✔
503

504
                // Check if it's a unit variant which is represented as a string
505
                if self.peek_string()? {
3✔
506
                    let variant_name = self.decode_string()?;
2✔
507
                    for (idx, variant) in enum_type.variants.iter().enumerate() {
3✔
508
                        if variant.name == variant_name {
3✔
509
                            return wip.variant(idx).map_err(DecodeError::ReflectError);
2✔
510
                        }
1✔
511
                    }
NEW
512
                    return Err(DecodeError::InvalidEnum(format!(
×
NEW
513
                        "Unknown variant: {}",
×
NEW
514
                        variant_name
×
NEW
515
                    )));
×
516
                }
1✔
517

518
                // Otherwise it's represented as a map with single entry where key is the variant name
519
                let map_len = self.decode_map_len()?;
1✔
520
                if map_len != 1 {
1✔
NEW
521
                    return Err(DecodeError::InvalidData);
×
522
                }
1✔
523

524
                let variant_name = self.decode_string()?;
1✔
525

526
                for (idx, variant) in enum_type.variants.iter().enumerate() {
2✔
527
                    if variant.name == variant_name {
2✔
528
                        match &variant.data.kind {
1✔
529
                            // Handle unit variant
530
                            facet_core::StructKind::Unit => {
531
                                // Need to skip any value that might be present
NEW
532
                                self.skip_value()?;
×
NEW
533
                                return wip.variant(idx).map_err(DecodeError::ReflectError);
×
534
                            }
535

536
                            // Handle tuple variant
537
                            facet_core::StructKind::Tuple => {
NEW
538
                                let array_len = self.decode_array_len()?;
×
NEW
539
                                let field_count = variant.data.fields.len();
×
NEW
540

×
NEW
541
                                if array_len != field_count {
×
NEW
542
                                    return Err(DecodeError::InvalidData);
×
NEW
543
                                }
×
NEW
544

×
NEW
545
                                // First select the variant - not used since we return immediately
×
NEW
546
                                let _ = wip.variant(idx).map_err(DecodeError::ReflectError)?;
×
547

548
                                // Temporarily using a not-implemented error while we figure out the correct approach
NEW
549
                                return Err(DecodeError::NotImplemented(
×
NEW
550
                                    "Enum tuple variants not yet fully implemented".to_string(),
×
NEW
551
                                ));
×
552
                            }
553

554
                            // Handle struct variant
555
                            facet_core::StructKind::Struct => {
556
                                let map_len = self.decode_map_len()?;
1✔
557
                                // First select the variant
558
                                let mut enum_wip =
1✔
559
                                    wip.variant(idx).map_err(DecodeError::ReflectError)?;
1✔
560

561
                                // Handle fields as a normal struct
562
                                for _ in 0..map_len {
1✔
563
                                    let field_name = self.decode_string()?;
3✔
564
                                    match enum_wip.field_index(&field_name) {
3✔
565
                                        Some(field_idx) => {
3✔
566
                                            let field_wip = enum_wip
3✔
567
                                                .field(field_idx)
3✔
568
                                                .map_err(DecodeError::ReflectError)?;
3✔
569
                                            let field_wip = self.deserialize_value(field_wip)?;
3✔
570
                                            enum_wip = field_wip
3✔
571
                                                .pop()
3✔
572
                                                .map_err(DecodeError::ReflectError)?;
3✔
573
                                        }
574
                                        None => {
575
                                            // Skip unknown field
NEW
576
                                            self.skip_value()?;
×
NEW
577
                                            trace!(
×
NEW
578
                                                "Skipping unknown field in enum: {}",
×
579
                                                field_name
580
                                            );
581
                                        }
582
                                    }
583
                                }
584

585
                                return Ok(enum_wip);
1✔
586
                            }
587

588
                            // Handle other kinds that might be added in the future
589
                            _ => {
NEW
590
                                return Err(DecodeError::UnsupportedType(format!(
×
NEW
591
                                    "Unsupported enum variant kind: {:?}",
×
NEW
592
                                    variant.data.kind
×
NEW
593
                                )));
×
594
                            }
595
                        }
596
                    }
1✔
597
                }
598

NEW
599
                return Err(DecodeError::InvalidEnum(format!(
×
NEW
600
                    "Unknown variant: {}",
×
NEW
601
                    variant_name
×
NEW
602
                )));
×
603
            }
604
            _ => {}
54✔
605
        }
54✔
606

54✔
607
        // Then check the def system (Def)
54✔
608
        if let Def::Scalar(_) = shape.def {
54✔
609
            trace!("Deserializing scalar");
43✔
610
            if shape.is_type::<String>() {
43✔
611
                let s = self.decode_string()?;
18✔
612
                wip = wip.put(s).map_err(DecodeError::ReflectError)?;
17✔
613
            } else if shape.is_type::<u64>() {
25✔
614
                let n = self.decode_u64()?;
15✔
615
                wip = wip.put(n).map_err(DecodeError::ReflectError)?;
15✔
616
            } else if shape.is_type::<u32>() {
10✔
NEW
617
                let n = self.decode_u64()?;
×
NEW
618
                if n > u32::MAX as u64 {
×
NEW
619
                    return Err(DecodeError::IntegerOverflow);
×
NEW
620
                }
×
NEW
621
                wip = wip.put(n as u32).map_err(DecodeError::ReflectError)?;
×
622
            } else if shape.is_type::<u16>() {
10✔
NEW
623
                let n = self.decode_u64()?;
×
NEW
624
                if n > u16::MAX as u64 {
×
NEW
625
                    return Err(DecodeError::IntegerOverflow);
×
NEW
626
                }
×
NEW
627
                wip = wip.put(n as u16).map_err(DecodeError::ReflectError)?;
×
628
            } else if shape.is_type::<u8>() {
10✔
NEW
629
                let n = self.decode_u64()?;
×
NEW
630
                if n > u8::MAX as u64 {
×
NEW
631
                    return Err(DecodeError::IntegerOverflow);
×
NEW
632
                }
×
NEW
633
                wip = wip.put(n as u8).map_err(DecodeError::ReflectError)?;
×
634
            } else if shape.is_type::<i64>() {
10✔
635
                // TODO: implement proper signed int decoding including negative values
NEW
636
                let n = self.decode_u64()?;
×
NEW
637
                if n > i64::MAX as u64 {
×
NEW
638
                    return Err(DecodeError::IntegerOverflow);
×
NEW
639
                }
×
NEW
640
                wip = wip.put(n as i64).map_err(DecodeError::ReflectError)?;
×
641
            } else if shape.is_type::<i32>() {
10✔
642
                let n = self.decode_u64()?;
7✔
643
                if n > i32::MAX as u64 {
7✔
NEW
644
                    return Err(DecodeError::IntegerOverflow);
×
645
                }
7✔
646
                wip = wip.put(n as i32).map_err(DecodeError::ReflectError)?;
7✔
647
            } else if shape.is_type::<i16>() {
3✔
NEW
648
                let n = self.decode_u64()?;
×
NEW
649
                if n > i16::MAX as u64 {
×
NEW
650
                    return Err(DecodeError::IntegerOverflow);
×
UNCOV
651
                }
×
NEW
652
                wip = wip.put(n as i16).map_err(DecodeError::ReflectError)?;
×
653
            } else if shape.is_type::<i8>() {
3✔
NEW
654
                let n = self.decode_u64()?;
×
NEW
655
                if n > i8::MAX as u64 {
×
NEW
656
                    return Err(DecodeError::IntegerOverflow);
×
NEW
657
                }
×
NEW
658
                wip = wip.put(n as i8).map_err(DecodeError::ReflectError)?;
×
659
            } else if shape.is_type::<f64>() {
3✔
660
                // TODO: Implement proper f64 decoding from MessagePack format
NEW
661
                return Err(DecodeError::NotImplemented(
×
NEW
662
                    "f64 deserialization not yet implemented".to_string(),
×
NEW
663
                ));
×
664
            } else if shape.is_type::<f32>() {
3✔
665
                // TODO: Implement proper f32 decoding from MessagePack format
NEW
666
                return Err(DecodeError::NotImplemented(
×
NEW
667
                    "f32 deserialization not yet implemented".to_string(),
×
NEW
668
                ));
×
669
            } else if shape.is_type::<bool>() {
3✔
670
                let b = self.decode_bool()?;
3✔
671
                wip = wip.put(b).map_err(DecodeError::ReflectError)?;
3✔
672
            } else {
NEW
673
                return Err(DecodeError::UnsupportedType(format!("{}", shape)));
×
674
            }
675
        } else if let Def::Map(_map_def) = shape.def {
11✔
676
            trace!("Deserializing map");
2✔
677
            let map_len = self.decode_map_len()?;
2✔
678
            let mut map_wip = wip.begin_map_insert().map_err(DecodeError::ReflectError)?;
2✔
679

680
            for _ in 0..map_len {
2✔
681
                // Each map entry has a key and value
682
                let key_wip = map_wip.push_map_key().map_err(DecodeError::ReflectError)?;
3✔
683
                let key_wip = self.deserialize_value(key_wip)?;
3✔
684

685
                let value_wip = key_wip
3✔
686
                    .push_map_value()
3✔
687
                    .map_err(DecodeError::ReflectError)?;
3✔
688
                let map_wip_next = self.deserialize_value(value_wip)?;
3✔
689

690
                map_wip = map_wip_next.pop().map_err(DecodeError::ReflectError)?;
3✔
691
            }
692

693
            wip = map_wip;
2✔
694
        } else if let Def::List(_list_def) = shape.def {
9✔
695
            trace!("Deserializing list");
6✔
696
            let array_len = self.decode_array_len()?;
6✔
697
            let mut list_wip = wip.begin_pushback().map_err(DecodeError::ReflectError)?;
6✔
698

699
            for _ in 0..array_len {
6✔
700
                let item_wip = list_wip.push().map_err(DecodeError::ReflectError)?;
13✔
701
                list_wip = self
13✔
702
                    .deserialize_value(item_wip)?
13✔
703
                    .pop()
13✔
704
                    .map_err(DecodeError::ReflectError)?;
13✔
705
            }
706

707
            wip = list_wip;
6✔
708
        } else if let Def::Option(_option_def) = shape.def {
3✔
709
            trace!("Deserializing option");
3✔
710
            // Check if we have a null/nil value
711
            if self.peek_nil()? {
3✔
712
                // Consume the nil value
713
                self.decode_nil()?;
1✔
714
                // Initialize None option
715
                wip = wip.put_default().map_err(DecodeError::ReflectError)?;
1✔
716
            } else {
717
                // Value is present - initialize a Some option
718
                let some_wip = wip.push_some().map_err(DecodeError::ReflectError)?;
2✔
719
                let some_wip = self.deserialize_value(some_wip)?;
2✔
720
                wip = some_wip.pop().map_err(DecodeError::ReflectError)?;
2✔
721
            }
722
        } else {
NEW
723
            return Err(DecodeError::UnsupportedShape(format!("{:?}", shape)));
×
724
        }
725

726
        Ok(wip)
53✔
727
    }
74✔
728
}
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